Salome HOME
a9c55c69725c1bc0f1cb7c6140a7d1d0c20144c7
[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 /// @cond INTERNAL
57 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
58 /// @endcond
59
60 MEDCouplingUMesh *MEDCouplingUMesh::New()
61 {
62   return new MEDCouplingUMesh;
63 }
64
65 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
66 {
67   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
68   ret->setName(meshName);
69   ret->setMeshDimension(meshDim);
70   return ret;
71 }
72
73 /*!
74  * Returns a new MEDCouplingUMesh which is a full copy of \a this one. No data is shared
75  * between \a this and the new mesh.
76  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
77  *          delete this mesh using decrRef() as it is no more needed. 
78  */
79 MEDCouplingUMesh *MEDCouplingUMesh::deepCpy() const
80 {
81   return clone(true);
82 }
83
84
85 /*!
86  * Returns a new MEDCouplingUMesh which is a copy of \a this one.
87  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
88  * this mesh are shared by the new mesh.
89  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
90  *          delete this mesh using decrRef() as it is no more needed. 
91  */
92 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
93 {
94   return new MEDCouplingUMesh(*this,recDeepCpy);
95 }
96
97 /*!
98  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
99  * The coordinates are shared between \a this and the returned instance.
100  * 
101  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
102  * \sa MEDCouplingUMesh::deepCpy
103  */
104 MEDCouplingUMesh *MEDCouplingUMesh::deepCpyConnectivityOnly() const
105 {
106   checkConnectivityFullyDefined();
107   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
108   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
109   ret->setConnectivity(c,ci);
110   return ret.retn();
111 }
112
113 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
114 {
115   if(!other)
116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
117   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
118   if(!otherC)
119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
120   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
121   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
122 }
123
124 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
125 {
126   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
127   return ret;
128 }
129
130 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
131 {
132   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
133   ret.push_back(_nodal_connec);
134   ret.push_back(_nodal_connec_index);
135   return ret;
136 }
137
138 void MEDCouplingUMesh::updateTime() const
139 {
140   MEDCouplingPointSet::updateTime();
141   if(_nodal_connec)
142     {
143       updateTimeWith(*_nodal_connec);
144     }
145   if(_nodal_connec_index)
146     {
147       updateTimeWith(*_nodal_connec_index);
148     }
149 }
150
151 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
152 {
153 }
154
155 /*!
156  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
157  * then \a this mesh is most probably is writable, exchangeable and available for most
158  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
159  * this method to check that all is in order with \a this mesh.
160  *  \throw If the mesh dimension is not set.
161  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
162  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
163  *  \throw If the connectivity data array has more than one component.
164  *  \throw If the connectivity data array has a named component.
165  *  \throw If the connectivity index data array has more than one component.
166  *  \throw If the connectivity index data array has a named component.
167  */
168 void MEDCouplingUMesh::checkCoherency() const
169 {
170   if(_mesh_dim<-1)
171     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
172   if(_mesh_dim!=-1)
173     MEDCouplingPointSet::checkCoherency();
174   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
175     {
176       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
177         {
178           std::ostringstream message;
179           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
180           throw INTERP_KERNEL::Exception(message.str().c_str());
181         }
182     }
183   if(_nodal_connec)
184     {
185       if(_nodal_connec->getNumberOfComponents()!=1)
186         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
187       if(_nodal_connec->getInfoOnComponent(0)!="")
188         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
189     }
190   else
191     if(_mesh_dim!=-1)
192       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
193   if(_nodal_connec_index)
194     {
195       if(_nodal_connec_index->getNumberOfComponents()!=1)
196         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
197       if(_nodal_connec_index->getInfoOnComponent(0)!="")
198         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
199     }
200   else
201     if(_mesh_dim!=-1)
202       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
203 }
204
205 /*!
206  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
207  * then \a this mesh is most probably is writable, exchangeable and available for all
208  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
209  * method thoroughly checks the nodal connectivity.
210  *  \param [in] eps - a not used parameter.
211  *  \throw If the mesh dimension is not set.
212  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
213  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
214  *  \throw If the connectivity data array has more than one component.
215  *  \throw If the connectivity data array has a named component.
216  *  \throw If the connectivity index data array has more than one component.
217  *  \throw If the connectivity index data array has a named component.
218  *  \throw If number of nodes defining an element does not correspond to the type of element.
219  *  \throw If the nodal connectivity includes an invalid node id.
220  */
221 void MEDCouplingUMesh::checkCoherency1(double eps) const
222 {
223   checkCoherency();
224   if(_mesh_dim==-1)
225     return ;
226   int meshDim=getMeshDimension();
227   int nbOfNodes=getNumberOfNodes();
228   int nbOfCells=getNumberOfCells();
229   const int *ptr=_nodal_connec->getConstPointer();
230   const int *ptrI=_nodal_connec_index->getConstPointer();
231   for(int i=0;i<nbOfCells;i++)
232     {
233       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
234       if((int)cm.getDimension()!=meshDim)
235         {
236           std::ostringstream oss;
237           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
238           throw INTERP_KERNEL::Exception(oss.str().c_str());
239         }
240       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
241       if(!cm.isDynamic())
242         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
243           {
244             std::ostringstream oss;
245             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
246             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
247             throw INTERP_KERNEL::Exception(oss.str().c_str());
248           }
249       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
250         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
251           {
252             std::ostringstream oss;
253             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
254             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
255             throw INTERP_KERNEL::Exception(oss.str().c_str());
256           }
257       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
258         {
259           int nodeId=*w;
260           if(nodeId>=0)
261             {
262               if(nodeId>=nbOfNodes)
263                 {
264                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
265                   throw INTERP_KERNEL::Exception(oss.str().c_str());
266                 }
267             }
268           else if(nodeId<-1)
269             {
270               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
271               throw INTERP_KERNEL::Exception(oss.str().c_str());
272             }
273           else
274             {
275               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
276                 {
277                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
278                   throw INTERP_KERNEL::Exception(oss.str().c_str());
279                 }
280             }
281         }
282     }
283 }
284
285
286 /*!
287  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
288  * then \a this mesh is most probably is writable, exchangeable and available for all
289  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
290  *  \param [in] eps - a not used parameter.
291  *  \throw If the mesh dimension is not set.
292  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
293  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
294  *  \throw If the connectivity data array has more than one component.
295  *  \throw If the connectivity data array has a named component.
296  *  \throw If the connectivity index data array has more than one component.
297  *  \throw If the connectivity index data array has a named component.
298  *  \throw If number of nodes defining an element does not correspond to the type of element.
299  *  \throw If the nodal connectivity includes an invalid node id.
300  */
301 void MEDCouplingUMesh::checkCoherency2(double eps) const
302 {
303   checkCoherency1(eps);
304 }
305
306 /*!
307  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
308  * elements contained in the mesh. For more info on the mesh dimension see
309  * \ref MEDCouplingUMeshPage.
310  *  \param [in] meshDim - a new mesh dimension.
311  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
312  */
313 void MEDCouplingUMesh::setMeshDimension(int meshDim)
314 {
315   if(meshDim<-1 || meshDim>3)
316     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
317   _mesh_dim=meshDim;
318   declareAsNew();
319 }
320
321 /*!
322  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
323  * 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.
324  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
325  *
326  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
327  *
328  *  \if ENABLE_EXAMPLES
329  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
330  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
331  *  \endif
332  */
333 void MEDCouplingUMesh::allocateCells(int nbOfCells)
334 {
335   if(nbOfCells<0)
336     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
337   if(_nodal_connec_index)
338     {
339       _nodal_connec_index->decrRef();
340     }
341   if(_nodal_connec)
342     {
343       _nodal_connec->decrRef();
344     }
345   _nodal_connec_index=DataArrayInt::New();
346   _nodal_connec_index->reserve(nbOfCells+1);
347   _nodal_connec_index->pushBackSilent(0);
348   _nodal_connec=DataArrayInt::New();
349   _nodal_connec->reserve(2*nbOfCells);
350   _types.clear();
351   declareAsNew();
352 }
353
354 /*!
355  * Appends a cell to the connectivity array. For deeper understanding what is
356  * happening see \ref MEDCouplingUMeshNodalConnectivity.
357  *  \param [in] type - type of cell to add.
358  *  \param [in] size - number of nodes constituting this cell.
359  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
360  * 
361  *  \if ENABLE_EXAMPLES
362  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
363  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
364  *  \endif
365  */
366 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
367 {
368   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
369   if(_nodal_connec_index==0)
370     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
371   if((int)cm.getDimension()==_mesh_dim)
372     {
373       if(!cm.isDynamic())
374         if(size!=(int)cm.getNumberOfNodes())
375           {
376             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
377             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
378             throw INTERP_KERNEL::Exception(oss.str().c_str());
379           }
380       int idx=_nodal_connec_index->back();
381       int val=idx+size+1;
382       _nodal_connec_index->pushBackSilent(val);
383       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
384       _types.insert(type);
385     }
386   else
387     {
388       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
389       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
390       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
391       throw INTERP_KERNEL::Exception(oss.str().c_str());
392     }
393 }
394
395 /*!
396  * Compacts data arrays to release unused memory. This method is to be called after
397  * finishing cell insertion using \a this->insertNextCell().
398  * 
399  *  \if ENABLE_EXAMPLES
400  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
401  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
402  *  \endif
403  */
404 void MEDCouplingUMesh::finishInsertingCells()
405 {
406   _nodal_connec->pack();
407   _nodal_connec_index->pack();
408   _nodal_connec->declareAsNew();
409   _nodal_connec_index->declareAsNew();
410   updateTime();
411 }
412
413 /*!
414  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
415  * Useful for python users.
416  */
417 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
418 {
419   return new MEDCouplingUMeshCellIterator(this);
420 }
421
422 /*!
423  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
424  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
425  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
426  * Useful for python users.
427  */
428 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
429 {
430   if(!checkConsecutiveCellTypes())
431     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
432   return new MEDCouplingUMeshCellByTypeEntry(this);
433 }
434
435 /*!
436  * Returns a set of all cell types available in \a this mesh.
437  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
438  * \warning this method does not throw any exception even if \a this is not defined.
439  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
440  */
441 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
442 {
443   return _types;
444 }
445
446 /*!
447  * This method returns the sorted list of geometric types in \a this.
448  * 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
449  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
450  *
451  * \throw if connectivity in \a this is not correctly defined.
452  *  
453  * \sa MEDCouplingMesh::getAllGeoTypes
454  */
455 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
456 {
457   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
458   checkConnectivityFullyDefined();
459   int nbOfCells(getNumberOfCells());
460   if(nbOfCells==0)
461     return ret;
462   if(getMeshLength()<1)
463     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
464   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
465   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
466   for(int i=1;i<nbOfCells;i++,ci++)
467     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
468       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
469   return ret;
470 }
471
472 /*!
473  * This method is a method that compares \a this and \a other.
474  * This method compares \b all attributes, even names and component names.
475  */
476 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
477 {
478   if(!other)
479     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
480   std::ostringstream oss; oss.precision(15);
481   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
482   if(!otherC)
483     {
484       reason="mesh given in input is not castable in MEDCouplingUMesh !";
485       return false;
486     }
487   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
488     return false;
489   if(_mesh_dim!=otherC->_mesh_dim)
490     {
491       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
492       reason=oss.str();
493       return false;
494     }
495   if(_types!=otherC->_types)
496     {
497       oss << "umesh geometric type mismatch :\nThis geometric types are :";
498       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
499         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
500       oss << "\nOther geometric types are :";
501       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
502         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
503       reason=oss.str();
504       return false;
505     }
506   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
507     if(_nodal_connec==0 || otherC->_nodal_connec==0)
508       {
509         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
510         return false;
511       }
512   if(_nodal_connec!=otherC->_nodal_connec)
513     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
514       {
515         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
516         return false;
517       }
518   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
519     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
520       {
521         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
522         return false;
523       }
524   if(_nodal_connec_index!=otherC->_nodal_connec_index)
525     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
526       {
527         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
528         return false;
529       }
530   return true;
531 }
532
533 /*!
534  * Checks if data arrays of this mesh (node coordinates, nodal
535  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
536  * not considered.
537  *  \param [in] other - the mesh to compare with.
538  *  \param [in] prec - precision value used to compare node coordinates.
539  *  \return bool - \a true if the two meshes are same.
540  */
541 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
542 {
543   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
544   if(!otherC)
545     return false;
546   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
547     return false;
548   if(_mesh_dim!=otherC->_mesh_dim)
549     return false;
550   if(_types!=otherC->_types)
551     return false;
552   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
553     if(_nodal_connec==0 || otherC->_nodal_connec==0)
554       return false;
555   if(_nodal_connec!=otherC->_nodal_connec)
556     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
557       return false;
558   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
559     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
560       return false;
561   if(_nodal_connec_index!=otherC->_nodal_connec_index)
562     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
563       return false;
564   return true;
565 }
566
567 /*!
568  * Checks if \a this and \a other meshes are geometrically equivalent with high
569  * probability, else an exception is thrown. The meshes are considered equivalent if
570  * (1) meshes contain the same number of nodes and the same number of elements of the
571  * same types (2) three cells of the two meshes (first, last and middle) are based
572  * on coincident nodes (with a specified precision).
573  *  \param [in] other - the mesh to compare with.
574  *  \param [in] prec - the precision used to compare nodes of the two meshes.
575  *  \throw If the two meshes do not match.
576  */
577 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
578 {
579   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
580   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
581   if(!otherC)
582     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
583 }
584
585 /*!
586  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
587  * cells each node belongs to.
588  * \warning For speed reasons, this method does not check if node ids in the nodal
589  *          connectivity correspond to the size of node coordinates array.
590  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
591  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
592  *        dividing cell ids in \a revNodal into groups each referring to one
593  *        node. Its every element (except the last one) is an index pointing to the
594  *         first id of a group of cells. For example cells sharing the node #1 are 
595  *        described by following range of indices: 
596  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
597  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
598  *        Number of cells sharing the *i*-th node is
599  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
600  * \throw If the coordinates array is not set.
601  * \throw If the nodal connectivity of cells is not defined.
602  * 
603  * \if ENABLE_EXAMPLES
604  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
605  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
606  * \endif
607  */
608 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
609 {
610   checkFullyDefined();
611   int nbOfNodes=getNumberOfNodes();
612   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
613   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
614   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
615   const int *conn=_nodal_connec->getConstPointer();
616   const int *connIndex=_nodal_connec_index->getConstPointer();
617   int nbOfCells=getNumberOfCells();
618   int nbOfEltsInRevNodal=0;
619   for(int eltId=0;eltId<nbOfCells;eltId++)
620     {
621       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
622       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
623       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
624         if(*iter>=0)//for polyhedrons
625           {
626             nbOfEltsInRevNodal++;
627             revNodalIndxPtr[(*iter)+1]++;
628           }
629     }
630   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
631   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
632   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
633   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
634   for(int eltId=0;eltId<nbOfCells;eltId++)
635     {
636       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
637       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
638       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
639         if(*iter>=0)//for polyhedrons
640           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
641     }
642 }
643
644 /// @cond INTERNAL
645
646 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
647 {
648   return id;
649 }
650
651 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
652 {
653   if(!compute)
654     return id+1;
655   else
656     {
657       if(cm.getOrientationStatus(nb,conn1,conn2))
658         return id+1;
659       else
660         return -(id+1);
661     }
662 }
663
664 class MinusOneSonsGenerator
665 {
666 public:
667   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
668   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
669   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
670   static const int DELTA=1;
671 private:
672   const INTERP_KERNEL::CellModel& _cm;
673 };
674
675 class MinusOneSonsGeneratorBiQuadratic
676 {
677 public:
678   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
679   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
680   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
681   static const int DELTA=1;
682 private:
683   const INTERP_KERNEL::CellModel& _cm;
684 };
685
686 class MinusTwoSonsGenerator
687 {
688 public:
689   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
690   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
691   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
692   static const int DELTA=2;
693 private:
694   const INTERP_KERNEL::CellModel& _cm;
695 };
696
697 /// @endcond
698
699 /*!
700  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
701  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
702  * describing correspondence between cells of \a this and the result meshes are
703  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
704  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
705  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
706  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
707  * \warning For speed reasons, this method does not check if node ids in the nodal
708  *          connectivity correspond to the size of node coordinates array.
709  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
710  *          to write this mesh to the MED file, its cells must be sorted using
711  *          sortCellsInMEDFileFrmt().
712  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
713  *         each cell of \a this mesh.
714  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
715  *        dividing cell ids in \a desc into groups each referring to one
716  *        cell of \a this mesh. Its every element (except the last one) is an index
717  *        pointing to the first id of a group of cells. For example cells of the
718  *        result mesh bounding the cell #1 of \a this mesh are described by following
719  *        range of indices:
720  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
721  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
722  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
723  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
724  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
725  *         by each cell of the result mesh.
726  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
727  *        in the result mesh,
728  *        dividing cell ids in \a revDesc into groups each referring to one
729  *        cell of the result mesh the same way as \a descIndx divides \a desc.
730  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
731  *        delete this mesh using decrRef() as it is no more needed.
732  *  \throw If the coordinates array is not set.
733  *  \throw If the nodal connectivity of cells is node defined.
734  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
735  *         revDescIndx == NULL.
736  * 
737  *  \if ENABLE_EXAMPLES
738  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
739  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
740  *  \endif
741  * \sa buildDescendingConnectivity2()
742  */
743 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
744 {
745   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
746 }
747
748 /*!
749  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
750  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
751  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
752  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
753  * \sa MEDCouplingUMesh::buildDescendingConnectivity
754  */
755 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
756 {
757   checkFullyDefined();
758   if(getMeshDimension()!=3)
759     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
760   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
761 }
762
763 /*!
764  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
765  * this->getMeshDimension(), that bound cells of \a this mesh. In
766  * addition arrays describing correspondence between cells of \a this and the result
767  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
768  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
769  *  mesh. This method differs from buildDescendingConnectivity() in that apart
770  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
771  * result meshes. So a positive id means that order of nodes in corresponding cells
772  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
773  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
774  * i.e. cell ids are one-based.
775  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
776  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
777  * \warning For speed reasons, this method does not check if node ids in the nodal
778  *          connectivity correspond to the size of node coordinates array.
779  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
780  *          to write this mesh to the MED file, its cells must be sorted using
781  *          sortCellsInMEDFileFrmt().
782  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
783  *         each cell of \a this mesh.
784  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
785  *        dividing cell ids in \a desc into groups each referring to one
786  *        cell of \a this mesh. Its every element (except the last one) is an index
787  *        pointing to the first id of a group of cells. For example cells of the
788  *        result mesh bounding the cell #1 of \a this mesh are described by following
789  *        range of indices:
790  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
791  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
792  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
793  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
794  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
795  *         by each cell of the result mesh.
796  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
797  *        in the result mesh,
798  *        dividing cell ids in \a revDesc into groups each referring to one
799  *        cell of the result mesh the same way as \a descIndx divides \a desc.
800  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
801  *        shares the node coordinates array with \a this mesh. The caller is to
802  *        delete this mesh using decrRef() as it is no more needed.
803  *  \throw If the coordinates array is not set.
804  *  \throw If the nodal connectivity of cells is node defined.
805  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
806  *         revDescIndx == NULL.
807  * 
808  *  \if ENABLE_EXAMPLES
809  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
810  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
811  *  \endif
812  * \sa buildDescendingConnectivity()
813  */
814 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
815 {
816   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
817 }
818
819 /*!
820  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
821  * For speed reasons no check of this will be done. This method calls
822  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
823  * This method lists cell by cell in \b this which are its neighbors. To compute the result
824  * only connectivities are considered.
825  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
826  * The format of return is hence \ref numbering-indirect.
827  *
828  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
829  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
830  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
831  * is equal to the last values in \b neighborsIndx.
832  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
833  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
834  */
835 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
836 {
837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
838   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
839   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
840   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
841   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
842   meshDM1=0;
843   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
844 }
845
846 /*!
847  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
848  * of MEDCouplingUMesh::computeNeighborsOfCells.
849  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
850  * typically the case to extract a set a neighbours,
851  * excluding a set of meshdim-1 cells in input descending connectivity.
852  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
853  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
854  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
855  * are considered.
856  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
857  *
858  * \param [in] desc descending connectivity array.
859  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
860  * \param [in] revDesc reverse descending connectivity array.
861  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
862  * \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
863  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
864  * \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.
865  */
866 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
867                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
868 {
869   if(!desc || !descIndx || !revDesc || !revDescIndx)
870     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
871   const int *descPtr=desc->getConstPointer();
872   const int *descIPtr=descIndx->getConstPointer();
873   const int *revDescPtr=revDesc->getConstPointer();
874   const int *revDescIPtr=revDescIndx->getConstPointer();
875   //
876   int nbCells=descIndx->getNumberOfTuples()-1;
877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
879   int *out1Ptr=out1->getPointer();
880   *out1Ptr++=0;
881   out0->reserve(desc->getNumberOfTuples());
882   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
883     {
884       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
885         {
886           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
887           s.erase(i);
888           out0->insertAtTheEnd(s.begin(),s.end());
889         }
890       *out1Ptr=out0->getNumberOfTuples();
891     }
892   neighbors=out0.retn();
893   neighborsIndx=out1.retn();
894 }
895
896 /*!
897  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
898  * For speed reasons no check of this will be done. This method calls
899  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
900  * This method lists node by node in \b this which are its neighbors. To compute the result
901  * only connectivities are considered.
902  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
903  *
904  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
905  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
906  * parameter allows to select the right part in this array (\ref numbering-indirect).
907  * The number of tuples is equal to the last values in \b neighborsIndx.
908  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
909  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
910  */
911 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
912 {
913   checkFullyDefined();
914   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
915   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
916   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
917   switch(mdim)
918   {
919     case 3:
920       {
921         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
922         break;
923       }
924     case 2:
925       {
926         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
927         break;
928       }
929     case 1:
930       {
931         mesh1D=const_cast<MEDCouplingUMesh *>(this);
932         mesh1D->incrRef();
933         break;
934       }
935     default:
936       {
937         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
938       }
939   }
940   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
941   mesh1D->getReverseNodalConnectivity(desc,descIndx);
942   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
943   ret0->alloc(desc->getNumberOfTuples(),1);
944   int *r0Pt(ret0->getPointer());
945   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
946   for(int i=0;i<nbNodes;i++,rni++)
947     {
948       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
949         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
950     }
951   neighbors=ret0.retn();
952   neighborsIdx=descIndx.retn();
953 }
954
955 /// @cond INTERNAL
956
957 /*!
958  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
959  * For speed reasons no check of this will be done.
960  */
961 template<class SonsGenerator>
962 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
963 {
964   if(!desc || !descIndx || !revDesc || !revDescIndx)
965     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
966   checkConnectivityFullyDefined();
967   int nbOfCells=getNumberOfCells();
968   int nbOfNodes=getNumberOfNodes();
969   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
970   int *revNodalIndxPtr=revNodalIndx->getPointer();
971   const int *conn=_nodal_connec->getConstPointer();
972   const int *connIndex=_nodal_connec_index->getConstPointer();
973   std::string name="Mesh constituent of "; name+=getName();
974   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
975   ret->setCoords(getCoords());
976   ret->allocateCells(2*nbOfCells);
977   descIndx->alloc(nbOfCells+1,1);
978   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
979   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
980   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
981     {
982       int pos=connIndex[eltId];
983       int posP1=connIndex[eltId+1];
984       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
985       SonsGenerator sg(cm);
986       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
987       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
988       for(unsigned i=0;i<nbOfSons;i++)
989         {
990           INTERP_KERNEL::NormalizedCellType cmsId;
991           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
992           for(unsigned k=0;k<nbOfNodesSon;k++)
993             if(tmp[k]>=0)
994               revNodalIndxPtr[tmp[k]+1]++;
995           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
996           revDesc2->pushBackSilent(eltId);
997         }
998       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
999     }
1000   int nbOfCellsM1=ret->getNumberOfCells();
1001   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
1002   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
1003   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
1004   int *revNodalPtr=revNodal->getPointer();
1005   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
1006   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
1007   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
1008     {
1009       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
1010       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
1011       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
1012         if(*iter>=0)//for polyhedrons
1013           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
1014     }
1015   //
1016   DataArrayInt *commonCells=0,*commonCellsI=0;
1017   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1018   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1019   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1020   int newNbOfCellsM1=-1;
1021   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1022                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1023   std::vector<bool> isImpacted(nbOfCellsM1,false);
1024   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1025     for(int work2=work[0];work2!=work[1];work2++)
1026       isImpacted[commonCellsPtr[work2]]=true;
1027   const int *o2nM1Ptr=o2nM1->getConstPointer();
1028   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1029   const int *n2oM1Ptr=n2oM1->getConstPointer();
1030   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1031   ret2->copyTinyInfoFrom(this);
1032   desc->alloc(descIndx->back(),1);
1033   int *descPtr=desc->getPointer();
1034   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1035   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1036     {
1037       if(!isImpacted[i])
1038         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1039       else
1040         {
1041           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1042             {
1043               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1044               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1045             }
1046           else
1047             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1048         }
1049     }
1050   revDesc->reserve(newNbOfCellsM1);
1051   revDescIndx->alloc(newNbOfCellsM1+1,1);
1052   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1053   const int *revDesc2Ptr=revDesc2->getConstPointer();
1054   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1055     {
1056       int oldCellIdM1=n2oM1Ptr[i];
1057       if(!isImpacted[oldCellIdM1])
1058         {
1059           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1060           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1061         }
1062       else
1063         {
1064           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1065             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1066           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1067           commonCellsIPtr++;
1068         }
1069     }
1070   //
1071   return ret2.retn();
1072 }
1073
1074 struct MEDCouplingAccVisit
1075 {
1076   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1077   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1078   int _new_nb_of_nodes;
1079 };
1080
1081 /// @endcond
1082
1083 /*!
1084  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1085  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1086  * array of cell ids. Pay attention that after conversion all algorithms work slower
1087  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1088  * conversion due presence of invalid ids in the array of cells to convert, as a
1089  * result \a this mesh contains some already converted elements. In this case the 2D
1090  * mesh remains valid but 3D mesh becomes \b inconsistent!
1091  *  \warning This method can significantly modify the order of geometric types in \a this,
1092  *          hence, to write this mesh to the MED file, its cells must be sorted using
1093  *          sortCellsInMEDFileFrmt().
1094  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1095  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1096  *         cellIdsToConvertBg.
1097  *  \throw If the coordinates array is not set.
1098  *  \throw If the nodal connectivity of cells is node defined.
1099  *  \throw If dimension of \a this mesh is not either 2 or 3.
1100  *
1101  *  \if ENABLE_EXAMPLES
1102  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1103  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1104  *  \endif
1105  */
1106 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1107 {
1108   checkFullyDefined();
1109   int dim=getMeshDimension();
1110   if(dim<2 || dim>3)
1111     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1112   int nbOfCells(getNumberOfCells());
1113   if(dim==2)
1114     {
1115       const int *connIndex=_nodal_connec_index->getConstPointer();
1116       int *conn=_nodal_connec->getPointer();
1117       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1118         {
1119           if(*iter>=0 && *iter<nbOfCells)
1120             {
1121               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1122               if(!cm.isQuadratic())
1123                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1124               else
1125                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1126             }
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     }
1135   else
1136     {
1137       int *connIndex(_nodal_connec_index->getPointer());
1138       const int *connOld(_nodal_connec->getConstPointer());
1139       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1140       std::vector<bool> toBeDone(nbOfCells,false);
1141       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1142         {
1143           if(*iter>=0 && *iter<nbOfCells)
1144             toBeDone[*iter]=true;
1145           else
1146             {
1147               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1148               oss << " in range [0," << nbOfCells << ") !";
1149               throw INTERP_KERNEL::Exception(oss.str().c_str());
1150             }
1151         }
1152       for(int cellId=0;cellId<nbOfCells;cellId++)
1153         {
1154           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1155           int lgthOld(posP1-pos-1);
1156           if(toBeDone[cellId])
1157             {
1158               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1159               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1160               int *tmp(new int[nbOfFaces*lgthOld+1]);
1161               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1162               for(unsigned j=0;j<nbOfFaces;j++)
1163                 {
1164                   INTERP_KERNEL::NormalizedCellType type;
1165                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1166                   work+=offset;
1167                   *work++=-1;
1168                 }
1169               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1170               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1171               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1172               delete [] tmp;
1173             }
1174           else
1175             {
1176               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1177               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1178             }
1179         }
1180       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1181     }
1182   computeTypes();
1183 }
1184
1185 /*!
1186  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1187  * polyhedrons (if \a this is a 3D mesh).
1188  *  \warning As this method is purely for user-friendliness and no optimization is
1189  *          done to avoid construction of a useless vector, this method can be costly
1190  *          in memory.
1191  *  \throw If the coordinates array is not set.
1192  *  \throw If the nodal connectivity of cells is node defined.
1193  *  \throw If dimension of \a this mesh is not either 2 or 3.
1194  */
1195 void MEDCouplingUMesh::convertAllToPoly()
1196 {
1197   int nbOfCells=getNumberOfCells();
1198   std::vector<int> cellIds(nbOfCells);
1199   for(int i=0;i<nbOfCells;i++)
1200     cellIds[i]=i;
1201   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1202 }
1203
1204 /*!
1205  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1206  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1207  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1208  * base facet of the volume and the second half of nodes describes an opposite facet
1209  * having the same number of nodes as the base one. This method converts such
1210  * connectivity to a valid polyhedral format where connectivity of each facet is
1211  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1212  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1213  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1214  * a correct orientation of the first facet of a polyhedron, else orientation of a
1215  * corrected cell is reverse.<br>
1216  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1217  * it releases the user from boring description of polyhedra connectivity in the valid
1218  * format.
1219  *  \throw If \a this->getMeshDimension() != 3.
1220  *  \throw If \a this->getSpaceDimension() != 3.
1221  *  \throw If the nodal connectivity of cells is not defined.
1222  *  \throw If the coordinates array is not set.
1223  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1224  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1225  *
1226  *  \if ENABLE_EXAMPLES
1227  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1228  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1229  *  \endif
1230  */
1231 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1232 {
1233   checkFullyDefined();
1234   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1235     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1236   int nbOfCells=getNumberOfCells();
1237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1238   newCi->alloc(nbOfCells+1,1);
1239   int *newci=newCi->getPointer();
1240   const int *ci=_nodal_connec_index->getConstPointer();
1241   const int *c=_nodal_connec->getConstPointer();
1242   newci[0]=0;
1243   for(int i=0;i<nbOfCells;i++)
1244     {
1245       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1246       if(type==INTERP_KERNEL::NORM_POLYHED)
1247         {
1248           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1249             {
1250               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1251               throw INTERP_KERNEL::Exception(oss.str().c_str());
1252             }
1253           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1254           if(n2%2!=0)
1255             {
1256               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 !";
1257               throw INTERP_KERNEL::Exception(oss.str().c_str());
1258             }
1259           int n1=(int)(n2/2);
1260           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)
1261         }
1262       else
1263         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1264     }
1265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1266   newC->alloc(newci[nbOfCells],1);
1267   int *newc=newC->getPointer();
1268   for(int i=0;i<nbOfCells;i++)
1269     {
1270       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1271       if(type==INTERP_KERNEL::NORM_POLYHED)
1272         {
1273           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1274           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1275           *newc++=-1;
1276           for(std::size_t j=0;j<n1;j++)
1277             {
1278               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1279               newc[n1+5*j]=-1;
1280               newc[n1+5*j+1]=c[ci[i]+1+j];
1281               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1282               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1283               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1284             }
1285           newc+=n1*6;
1286         }
1287       else
1288         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1289     }
1290   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1291   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1292 }
1293
1294
1295 /*!
1296  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1297  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1298  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1299  *          to write this mesh to the MED file, its cells must be sorted using
1300  *          sortCellsInMEDFileFrmt().
1301  * \return \c true if at least one cell has been converted, \c false else. In the
1302  *         last case the nodal connectivity remains unchanged.
1303  * \throw If the coordinates array is not set.
1304  * \throw If the nodal connectivity of cells is not defined.
1305  * \throw If \a this->getMeshDimension() < 0.
1306  */
1307 bool MEDCouplingUMesh::unPolyze()
1308 {
1309   checkFullyDefined();
1310   int mdim=getMeshDimension();
1311   if(mdim<0)
1312     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1313   if(mdim<=1)
1314     return false;
1315   int nbOfCells=getNumberOfCells();
1316   if(nbOfCells<1)
1317     return false;
1318   int initMeshLgth=getMeshLength();
1319   int *conn=_nodal_connec->getPointer();
1320   int *index=_nodal_connec_index->getPointer();
1321   int posOfCurCell=0;
1322   int newPos=0;
1323   int lgthOfCurCell;
1324   bool ret=false;
1325   for(int i=0;i<nbOfCells;i++)
1326     {
1327       lgthOfCurCell=index[i+1]-posOfCurCell;
1328       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1329       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1330       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1331       int newLgth;
1332       if(cm.isDynamic())
1333         {
1334           switch(cm.getDimension())
1335           {
1336             case 2:
1337               {
1338                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1339                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1340                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1341                 break;
1342               }
1343             case 3:
1344               {
1345                 int nbOfFaces,lgthOfPolyhConn;
1346                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1347                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1348                 break;
1349               }
1350             case 1:
1351               {
1352                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1353                 break;
1354               }
1355           }
1356           ret=ret || (newType!=type);
1357           conn[newPos]=newType;
1358           newPos+=newLgth+1;
1359           posOfCurCell=index[i+1];
1360           index[i+1]=newPos;
1361         }
1362       else
1363         {
1364           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1365           newPos+=lgthOfCurCell;
1366           posOfCurCell+=lgthOfCurCell;
1367           index[i+1]=newPos;
1368         }
1369     }
1370   if(newPos!=initMeshLgth)
1371     _nodal_connec->reAlloc(newPos);
1372   if(ret)
1373     computeTypes();
1374   return ret;
1375 }
1376
1377 /*!
1378  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1379  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1380  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1381  *
1382  * \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 
1383  *             precision.
1384  */
1385 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1386 {
1387   checkFullyDefined();
1388   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1389     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1390   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1391   coords->recenterForMaxPrecision(eps);
1392   //
1393   int nbOfCells=getNumberOfCells();
1394   const int *conn=_nodal_connec->getConstPointer();
1395   const int *index=_nodal_connec_index->getConstPointer();
1396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1397   connINew->alloc(nbOfCells+1,1);
1398   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1400   bool changed=false;
1401   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1402     {
1403       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1404         {
1405           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1406           changed=true;
1407         }
1408       else
1409         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1410       *connINewPtr=connNew->getNumberOfTuples();
1411     }
1412   if(changed)
1413     setConnectivity(connNew,connINew,false);
1414 }
1415
1416 /*!
1417  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1418  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1419  * the format of the returned DataArrayInt instance.
1420  * 
1421  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1422  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1423  */
1424 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1425 {
1426   checkConnectivityFullyDefined();
1427   int nbOfCells=getNumberOfCells();
1428   const int *connIndex=_nodal_connec_index->getConstPointer();
1429   const int *conn=_nodal_connec->getConstPointer();
1430   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1431   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1432   std::vector<bool> retS(maxElt,false);
1433   for(int i=0;i<nbOfCells;i++)
1434     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1435       if(conn[j]>=0)
1436         retS[conn[j]]=true;
1437   int sz=0;
1438   for(int i=0;i<maxElt;i++)
1439     if(retS[i])
1440       sz++;
1441   DataArrayInt *ret=DataArrayInt::New();
1442   ret->alloc(sz,1);
1443   int *retPtr=ret->getPointer();
1444   for(int i=0;i<maxElt;i++)
1445     if(retS[i])
1446       *retPtr++=i;
1447   return ret;
1448 }
1449
1450 /*!
1451  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1452  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1453  */
1454 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1455 {
1456   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1457   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1458   for(int i=0;i<nbOfCells;i++)
1459     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1460       if(conn[j]>=0)
1461         {
1462           if(conn[j]<nbOfNodes)
1463             nodeIdsInUse[conn[j]]=true;
1464           else
1465             {
1466               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1467               throw INTERP_KERNEL::Exception(oss.str().c_str());
1468             }
1469         }
1470 }
1471
1472 /*!
1473  * Finds nodes not used in any cell and returns an array giving a new id to every node
1474  * by excluding the unused nodes, for which the array holds -1. The result array is
1475  * a mapping in "Old to New" mode. 
1476  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1477  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1478  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1479  *          if the node is unused or a new id else. The caller is to delete this
1480  *          array using decrRef() as it is no more needed.  
1481  *  \throw If the coordinates array is not set.
1482  *  \throw If the nodal connectivity of cells is not defined.
1483  *  \throw If the nodal connectivity includes an invalid id.
1484  *
1485  *  \if ENABLE_EXAMPLES
1486  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1487  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1488  *  \endif
1489  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1490  */
1491 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1492 {
1493   nbrOfNodesInUse=-1;
1494   int nbOfNodes(getNumberOfNodes());
1495   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1496   ret->alloc(nbOfNodes,1);
1497   int *traducer=ret->getPointer();
1498   std::fill(traducer,traducer+nbOfNodes,-1);
1499   int nbOfCells=getNumberOfCells();
1500   const int *connIndex=_nodal_connec_index->getConstPointer();
1501   const int *conn=_nodal_connec->getConstPointer();
1502   for(int i=0;i<nbOfCells;i++)
1503     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1504       if(conn[j]>=0)
1505         {
1506           if(conn[j]<nbOfNodes)
1507             traducer[conn[j]]=1;
1508           else
1509             {
1510               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1511               throw INTERP_KERNEL::Exception(oss.str().c_str());
1512             }
1513         }
1514   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1515   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1516   return ret.retn();
1517 }
1518
1519 /*!
1520  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1521  * For each cell in \b this the number of nodes constituting cell is computed.
1522  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1523  * So for pohyhedrons some nodes can be counted several times in the returned result.
1524  * 
1525  * \return a newly allocated array
1526  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1527  */
1528 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1529 {
1530   checkConnectivityFullyDefined();
1531   int nbOfCells=getNumberOfCells();
1532   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1533   ret->alloc(nbOfCells,1);
1534   int *retPtr=ret->getPointer();
1535   const int *conn=getNodalConnectivity()->getConstPointer();
1536   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1537   for(int i=0;i<nbOfCells;i++,retPtr++)
1538     {
1539       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1540         *retPtr=connI[i+1]-connI[i]-1;
1541       else
1542         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1543     }
1544   return ret.retn();
1545 }
1546
1547 /*!
1548  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1549  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1550  *
1551  * \return DataArrayInt * - new object to be deallocated by the caller.
1552  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1553  */
1554 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1555 {
1556   checkConnectivityFullyDefined();
1557   int nbOfCells=getNumberOfCells();
1558   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1559   ret->alloc(nbOfCells,1);
1560   int *retPtr=ret->getPointer();
1561   const int *conn=getNodalConnectivity()->getConstPointer();
1562   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1563   for(int i=0;i<nbOfCells;i++,retPtr++)
1564     {
1565       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1566       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1567         *retPtr=(int)s.size();
1568       else
1569         {
1570           s.erase(-1);
1571           *retPtr=(int)s.size();
1572         }
1573     }
1574   return ret.retn();
1575 }
1576
1577 /*!
1578  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1579  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1580  * 
1581  * \return a newly allocated array
1582  */
1583 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1584 {
1585   checkConnectivityFullyDefined();
1586   int nbOfCells=getNumberOfCells();
1587   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1588   ret->alloc(nbOfCells,1);
1589   int *retPtr=ret->getPointer();
1590   const int *conn=getNodalConnectivity()->getConstPointer();
1591   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1592   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1593     {
1594       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1595       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1596     }
1597   return ret.retn();
1598 }
1599
1600 /*!
1601  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1602  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1603  * array mean that the corresponding old node is no more used. 
1604  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1605  *           this->getNumberOfNodes() before call of this method. The caller is to
1606  *           delete this array using decrRef() as it is no more needed. 
1607  *  \throw If the coordinates array is not set.
1608  *  \throw If the nodal connectivity of cells is not defined.
1609  *  \throw If the nodal connectivity includes an invalid id.
1610  *  \sa areAllNodesFetched
1611  *
1612  *  \if ENABLE_EXAMPLES
1613  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1614  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1615  *  \endif
1616  */
1617 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1618 {
1619   return MEDCouplingPointSet::zipCoordsTraducer();
1620 }
1621
1622 /*!
1623  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1624  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1625  */
1626 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1627 {
1628   switch(compType)
1629   {
1630     case 0:
1631       return AreCellsEqual0(conn,connI,cell1,cell2);
1632     case 1:
1633       return AreCellsEqual1(conn,connI,cell1,cell2);
1634     case 2:
1635       return AreCellsEqual2(conn,connI,cell1,cell2);
1636     case 3:
1637       return AreCellsEqual3(conn,connI,cell1,cell2);
1638     case 7:
1639       return AreCellsEqual7(conn,connI,cell1,cell2);
1640   }
1641   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1642 }
1643
1644 /*!
1645  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1646  */
1647 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1648 {
1649   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1650     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1651   return 0;
1652 }
1653
1654 /*!
1655  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1656  */
1657 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1658 {
1659   int sz=connI[cell1+1]-connI[cell1];
1660   if(sz==connI[cell2+1]-connI[cell2])
1661     {
1662       if(conn[connI[cell1]]==conn[connI[cell2]])
1663         {
1664           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1665           unsigned dim=cm.getDimension();
1666           if(dim!=3)
1667             {
1668               if(dim!=1)
1669                 {
1670                   int sz1=2*(sz-1);
1671                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1672                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1673                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1674                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1675                   return work!=tmp+sz1?1:0;
1676                 }
1677               else
1678                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1679             }
1680           else
1681             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1682         }
1683     }
1684   return 0;
1685 }
1686
1687 /*!
1688  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1689  */
1690 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1691 {
1692   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1693     {
1694       if(conn[connI[cell1]]==conn[connI[cell2]])
1695         {
1696           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1697           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1698           return s1==s2?1:0;
1699         }
1700     }
1701   return 0;
1702 }
1703
1704 /*!
1705  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1706  */
1707 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1708 {
1709   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1710     {
1711       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1712       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1713       return s1==s2?1:0;
1714     }
1715   return 0;
1716 }
1717
1718 /*!
1719  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1720  */
1721 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1722 {
1723   int sz=connI[cell1+1]-connI[cell1];
1724   if(sz==connI[cell2+1]-connI[cell2])
1725     {
1726       if(conn[connI[cell1]]==conn[connI[cell2]])
1727         {
1728           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1729           unsigned dim=cm.getDimension();
1730           if(dim!=3)
1731             {
1732               if(dim!=1)
1733                 {
1734                   int sz1=2*(sz-1);
1735                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1736                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1737                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1738                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1739                   if(work!=tmp+sz1)
1740                     return 1;
1741                   else
1742                     {
1743                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1744                       std::reverse_iterator<int *> it2((int *)tmp);
1745                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1746                         return 2;
1747                       else
1748                         return 0;
1749                     }
1750
1751                   return work!=tmp+sz1?1:0;
1752                 }
1753               else
1754                 {//case of SEG2 and SEG3
1755                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1756                     return 1;
1757                   if(!cm.isQuadratic())
1758                     {
1759                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1760                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1761                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1762                         return 2;
1763                       return 0;
1764                     }
1765                   else
1766                     {
1767                       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])
1768                         return 2;
1769                       return 0;
1770                     }
1771                 }
1772             }
1773           else
1774             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1775         }
1776     }
1777   return 0;
1778 }
1779
1780 /*!
1781  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1782  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1783  * and result remains unchanged.
1784  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1785  * If in 'candidates' pool -1 value is considered as an empty value.
1786  * WARNING this method returns only ONE set of result !
1787  */
1788 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1789 {
1790   if(candidates.size()<1)
1791     return false;
1792   bool ret=false;
1793   std::vector<int>::const_iterator iter=candidates.begin();
1794   int start=(*iter++);
1795   for(;iter!=candidates.end();iter++)
1796     {
1797       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1798       if(status!=0)
1799         {
1800           if(!ret)
1801             {
1802               result->pushBackSilent(start);
1803               ret=true;
1804             }
1805           if(status==1)
1806             result->pushBackSilent(*iter);
1807           else
1808             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1809         }
1810     }
1811   return ret;
1812 }
1813
1814 /*!
1815  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1816  * by \a compType.
1817  * This method keeps the coordiantes of \a this. This method is time consuming.
1818  *
1819  * \param [in] compType input specifying the technique used to compare cells each other.
1820  *   - 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.
1821  *   - 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)
1822  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1823  *   - 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
1824  * can be used for users not sensitive to orientation of cell
1825  * \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.
1826  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1827  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1828  * \return the correspondance array old to new in a newly allocated array.
1829  * 
1830  */
1831 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1832 {
1833   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1834   getReverseNodalConnectivity(revNodal,revNodalI);
1835   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1836 }
1837
1838 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1839                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1840 {
1841   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1842   int nbOfCells=nodalI->getNumberOfTuples()-1;
1843   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1844   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1845   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1846   std::vector<bool> isFetched(nbOfCells,false);
1847   if(startCellId==0)
1848     {
1849       for(int i=0;i<nbOfCells;i++)
1850         {
1851           if(!isFetched[i])
1852             {
1853               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1854               std::vector<int> v,v2;
1855               if(connOfNode!=connPtr+connIPtr[i+1])
1856                 {
1857                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1858                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1859                   connOfNode++;
1860                 }
1861               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1862                 if(*connOfNode>=0)
1863                   {
1864                     v=v2;
1865                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1866                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1867                     v2.resize(std::distance(v2.begin(),it));
1868                   }
1869               if(v2.size()>1)
1870                 {
1871                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1872                     {
1873                       int pos=commonCellsI->back();
1874                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1875                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1876                         isFetched[*it]=true;
1877                     }
1878                 }
1879             }
1880         }
1881     }
1882   else
1883     {
1884       for(int i=startCellId;i<nbOfCells;i++)
1885         {
1886           if(!isFetched[i])
1887             {
1888               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1889               std::vector<int> v,v2;
1890               if(connOfNode!=connPtr+connIPtr[i+1])
1891                 {
1892                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1893                   connOfNode++;
1894                 }
1895               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1896                 if(*connOfNode>=0)
1897                   {
1898                     v=v2;
1899                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1900                     v2.resize(std::distance(v2.begin(),it));
1901                   }
1902               if(v2.size()>1)
1903                 {
1904                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1905                     {
1906                       int pos=commonCellsI->back();
1907                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1908                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1909                         isFetched[*it]=true;
1910                     }
1911                 }
1912             }
1913         }
1914     }
1915   commonCellsArr=commonCells.retn();
1916   commonCellsIArr=commonCellsI.retn();
1917 }
1918
1919 /*!
1920  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1921  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1922  * than \a other->getNumberOfCells() in the returned array means that there is no
1923  * corresponding cell in \a this mesh.
1924  * It is expected that \a this and \a other meshes share the same node coordinates
1925  * array, if it is not so an exception is thrown. 
1926  *  \param [in] other - the mesh to compare with.
1927  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1928  *         valid values [0,1,2], see zipConnectivityTraducer().
1929  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1930  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1931  *         values. The caller is to delete this array using
1932  *         decrRef() as it is no more needed.
1933  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1934  *         mesh.
1935  *
1936  *  \if ENABLE_EXAMPLES
1937  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1938  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1939  *  \endif
1940  *  \sa checkDeepEquivalOnSameNodesWith()
1941  *  \sa checkGeoEquivalWith()
1942  */
1943 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1944 {
1945   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1946   int nbOfCells=getNumberOfCells();
1947   static const int possibleCompType[]={0,1,2};
1948   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1949     {
1950       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1951       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1952       oss << " !";
1953       throw INTERP_KERNEL::Exception(oss.str().c_str());
1954     }
1955   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1956   arr=o2n->substr(nbOfCells);
1957   arr->setName(other->getName());
1958   int tmp;
1959   if(other->getNumberOfCells()==0)
1960     return true;
1961   return arr->getMaxValue(tmp)<nbOfCells;
1962 }
1963
1964 /*!
1965  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1966  * This method tries to determine if \b other is fully included in \b this.
1967  * The main difference is that this method is not expected to throw exception.
1968  * This method has two outputs :
1969  *
1970  * \param other other mesh
1971  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1972  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1973  */
1974 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1975 {
1976   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1977   DataArrayInt *commonCells=0,*commonCellsI=0;
1978   int thisNbCells=getNumberOfCells();
1979   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1980   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1981   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1982   int otherNbCells=other->getNumberOfCells();
1983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1984   arr2->alloc(otherNbCells,1);
1985   arr2->fillWithZero();
1986   int *arr2Ptr=arr2->getPointer();
1987   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1988   for(int i=0;i<nbOfCommon;i++)
1989     {
1990       int start=commonCellsPtr[commonCellsIPtr[i]];
1991       if(start<thisNbCells)
1992         {
1993           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1994             {
1995               int sig=commonCellsPtr[j]>0?1:-1;
1996               int val=std::abs(commonCellsPtr[j])-1;
1997               if(val>=thisNbCells)
1998                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1999             }
2000         }
2001     }
2002   arr2->setName(other->getName());
2003   if(arr2->presenceOfValue(0))
2004     return false;
2005   arr=arr2.retn();
2006   return true;
2007 }
2008
2009 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
2010 {
2011   if(!other)
2012     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
2013   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
2014   if(!otherC)
2015     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
2016   std::vector<const MEDCouplingUMesh *> ms(2);
2017   ms[0]=this;
2018   ms[1]=otherC;
2019   return MergeUMeshesOnSameCoords(ms);
2020 }
2021
2022 /*!
2023  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2024  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2025  * cellIds is not given explicitely but by a range python like.
2026  * 
2027  * \param start
2028  * \param end
2029  * \param step
2030  * \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.
2031  * \return a newly allocated
2032  * 
2033  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2034  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2035  */
2036 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2037 {
2038   if(getMeshDimension()!=-1)
2039     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords));
2040   else
2041     {
2042       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2043       if(newNbOfCells!=1)
2044         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2045       if(start!=0)
2046         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2047       incrRef();
2048       return const_cast<MEDCouplingUMesh *>(this);
2049     }
2050 }
2051
2052 /*!
2053  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2054  * The result mesh shares or not the node coordinates array with \a this mesh depending
2055  * on \a keepCoords parameter.
2056  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2057  *           to write this mesh to the MED file, its cells must be sorted using
2058  *           sortCellsInMEDFileFrmt().
2059  *  \param [in] begin - an array of cell ids to include to the new mesh.
2060  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2061  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2062  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2063  *         by calling zipCoords().
2064  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2065  *         to delete this mesh using decrRef() as it is no more needed. 
2066  *  \throw If the coordinates array is not set.
2067  *  \throw If the nodal connectivity of cells is not defined.
2068  *  \throw If any cell id in the array \a begin is not valid.
2069  *
2070  *  \if ENABLE_EXAMPLES
2071  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2072  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2073  *  \endif
2074  */
2075 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2076 {
2077   if(getMeshDimension()!=-1)
2078     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
2079   else
2080     {
2081       if(end-begin!=1)
2082         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2083       if(begin[0]!=0)
2084         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2085       incrRef();
2086       return const_cast<MEDCouplingUMesh *>(this);
2087     }
2088 }
2089
2090 /*!
2091  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2092  *
2093  * 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.
2094  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2095  * The number of cells of \b this will remain the same with this method.
2096  *
2097  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2098  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2099  * \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 ).
2100  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2101  */
2102 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2103 {
2104   checkConnectivityFullyDefined();
2105   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2106   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2107     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2108   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2109     {
2110       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2111       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2112       throw INTERP_KERNEL::Exception(oss.str().c_str());
2113     }
2114   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2115   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2116     {
2117       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2118       throw INTERP_KERNEL::Exception(oss.str().c_str());
2119     }
2120   int nbOfCells=getNumberOfCells();
2121   bool easyAssign=true;
2122   const int *connI=_nodal_connec_index->getConstPointer();
2123   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2124   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2125     {
2126       if(*it>=0 && *it<nbOfCells)
2127         {
2128           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2129         }
2130       else
2131         {
2132           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2133           throw INTERP_KERNEL::Exception(oss.str().c_str());
2134         }
2135     }
2136   if(easyAssign)
2137     {
2138       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2139       computeTypes();
2140     }
2141   else
2142     {
2143       DataArrayInt *arrOut=0,*arrIOut=0;
2144       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2145                                                arrOut,arrIOut);
2146       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2147       setConnectivity(arrOut,arrIOut,true);
2148     }
2149 }
2150
2151 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2152 {
2153   checkConnectivityFullyDefined();
2154   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2155   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2156     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2157   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2158     {
2159       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2160       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2161       throw INTERP_KERNEL::Exception(oss.str().c_str());
2162     }
2163   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2164   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2165     {
2166       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2167       throw INTERP_KERNEL::Exception(oss.str().c_str());
2168     }
2169   int nbOfCells=getNumberOfCells();
2170   bool easyAssign=true;
2171   const int *connI=_nodal_connec_index->getConstPointer();
2172   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2173   int it=start;
2174   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2175     {
2176       if(it>=0 && it<nbOfCells)
2177         {
2178           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2179         }
2180       else
2181         {
2182           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2183           throw INTERP_KERNEL::Exception(oss.str().c_str());
2184         }
2185     }
2186   if(easyAssign)
2187     {
2188       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2189       computeTypes();
2190     }
2191   else
2192     {
2193       DataArrayInt *arrOut=0,*arrIOut=0;
2194       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2195                                                 arrOut,arrIOut);
2196       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2197       setConnectivity(arrOut,arrIOut,true);
2198     }
2199 }                      
2200
2201 /*!
2202  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2203  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2204  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2205  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2206  *
2207  * \param [in] begin input start of array of node ids.
2208  * \param [in] end input end of array of node ids.
2209  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2210  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2211  */
2212 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2213 {
2214   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2215   checkConnectivityFullyDefined();
2216   int tmp=-1;
2217   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2218   std::vector<bool> fastFinder(sz,false);
2219   for(const int *work=begin;work!=end;work++)
2220     if(*work>=0 && *work<sz)
2221       fastFinder[*work]=true;
2222   int nbOfCells=getNumberOfCells();
2223   const int *conn=getNodalConnectivity()->getConstPointer();
2224   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2225   for(int i=0;i<nbOfCells;i++)
2226     {
2227       int ref=0,nbOfHit=0;
2228       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2229         if(*work2>=0)
2230           {
2231             ref++;
2232             if(fastFinder[*work2])
2233               nbOfHit++;
2234           }
2235       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2236         cellIdsKept->pushBackSilent(i);
2237     }
2238   cellIdsKeptArr=cellIdsKept.retn();
2239 }
2240
2241 /*!
2242  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2243  * this->getMeshDimension(), that bound some cells of \a this mesh.
2244  * The cells of lower dimension to include to the result mesh are selected basing on
2245  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2246  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2247  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2248  * created mesh shares the node coordinates array with \a this mesh. 
2249  *  \param [in] begin - the array of node ids.
2250  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2251  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2252  *         array \a begin are added, else cells whose any node is in the
2253  *         array \a begin are added.
2254  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2255  *         to delete this mesh using decrRef() as it is no more needed. 
2256  *  \throw If the coordinates array is not set.
2257  *  \throw If the nodal connectivity of cells is not defined.
2258  *  \throw If any node id in \a begin is not valid.
2259  *
2260  *  \if ENABLE_EXAMPLES
2261  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2262  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2263  *  \endif
2264  */
2265 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2266 {
2267   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2268   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2269   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2270   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2271   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2272 }
2273
2274 /*!
2275  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2276  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2277  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2278  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2279  *         by calling zipCoords().
2280  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2281  *         to delete this mesh using decrRef() as it is no more needed. 
2282  *  \throw If the coordinates array is not set.
2283  *  \throw If the nodal connectivity of cells is not defined.
2284  *
2285  *  \if ENABLE_EXAMPLES
2286  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2287  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2288  *  \endif
2289  */
2290 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2291 {
2292   DataArrayInt *desc=DataArrayInt::New();
2293   DataArrayInt *descIndx=DataArrayInt::New();
2294   DataArrayInt *revDesc=DataArrayInt::New();
2295   DataArrayInt *revDescIndx=DataArrayInt::New();
2296   //
2297   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2298   revDesc->decrRef();
2299   desc->decrRef();
2300   descIndx->decrRef();
2301   int nbOfCells=meshDM1->getNumberOfCells();
2302   const int *revDescIndxC=revDescIndx->getConstPointer();
2303   std::vector<int> boundaryCells;
2304   for(int i=0;i<nbOfCells;i++)
2305     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2306       boundaryCells.push_back(i);
2307   revDescIndx->decrRef();
2308   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2309   return ret;
2310 }
2311
2312 /*!
2313  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2314  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2315  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2316  */
2317 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2318 {
2319   checkFullyDefined();
2320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2321   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2323   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2324   //
2325   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2326   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2327   //
2328   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2329   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2330   const int *revDescPtr=revDesc->getConstPointer();
2331   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2332   int nbOfCells=getNumberOfCells();
2333   std::vector<bool> ret1(nbOfCells,false);
2334   int sz=0;
2335   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2336     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2337       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2338   //
2339   DataArrayInt *ret2=DataArrayInt::New();
2340   ret2->alloc(sz,1);
2341   int *ret2Ptr=ret2->getPointer();
2342   sz=0;
2343   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2344     if(*it)
2345       *ret2Ptr++=sz;
2346   ret2->setName("BoundaryCells");
2347   return ret2;
2348 }
2349
2350 /*!
2351  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2352  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2353  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2354  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2355  *
2356  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2357  * 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
2358  * equals a cell in \b otherDimM1OnSameCoords.
2359  *
2360  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2361  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2362  *
2363  * \param [in] otherDimM1OnSameCoords
2364  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2365  * \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
2366  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2367  */
2368 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2369 {
2370   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2371     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2372   checkConnectivityFullyDefined();
2373   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2374   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2375     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2377   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2378   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2379   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2380   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2381   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2382   DataArrayInt *idsOtherInConsti=0;
2383   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2384   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2385   if(!b)
2386     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2387   std::set<int> s1;
2388   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2389     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2391   s1arr_renum1->sort();
2392   cellIdsRk0=s0arr.retn();
2393   //cellIdsRk1=s_renum1.retn();
2394   cellIdsRk1=s1arr_renum1.retn();
2395 }
2396
2397 /*!
2398  * 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
2399  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2400  * 
2401  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2402  */
2403 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2404 {
2405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2406   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2407   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2408   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2409   //
2410   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2411   revDesc=0; desc=0; descIndx=0;
2412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2413   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2414   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2415 }
2416
2417 /*!
2418  * Finds nodes lying on the boundary of \a this mesh.
2419  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2420  *          nodes. The caller is to delete this array using decrRef() as it is no
2421  *          more needed.
2422  *  \throw If the coordinates array is not set.
2423  *  \throw If the nodal connectivity of cells is node defined.
2424  *
2425  *  \if ENABLE_EXAMPLES
2426  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2427  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2428  *  \endif
2429  */
2430 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2431 {
2432   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2433   return skin->computeFetchedNodeIds();
2434 }
2435
2436 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2437 {
2438   incrRef();
2439   return const_cast<MEDCouplingUMesh *>(this);
2440 }
2441
2442 /*!
2443  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2444  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2445  * 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.
2446  * 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.
2447  * 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.
2448  *
2449  * \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
2450  *             parameter is altered during the call.
2451  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2452  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2453  * \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.
2454  *
2455  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2456  */
2457 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2458                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2459 {
2460   typedef MEDCouplingAutoRefCountObjectPtr<DataArrayInt> DAInt;
2461
2462   checkFullyDefined();
2463   otherDimM1OnSameCoords.checkFullyDefined();
2464   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2465     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2466   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2467     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2468   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2469   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2470   DAInt cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2471   DAInt s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2472   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2473   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2474   DAInt s1=m0Part->computeFetchedNodeIds();
2475   DAInt s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2476   DAInt s3=s2->buildSubstraction(s1);
2477   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2478   //
2479   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2480   int nCells2 = m0Part2->getNumberOfCells();
2481   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2482   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2483   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2484   DataArrayInt *tmp00=0,*tmp11=0;
2485   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2486   DAInt neighInit00(tmp00);
2487   DAInt neighIInit00(tmp11);
2488   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2489   DataArrayInt *idsTmp=0;
2490   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2491   DAInt ids(idsTmp);
2492   if(!b)
2493     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2494   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2495   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2496   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2497   DataArrayInt *tmp0=0,*tmp1=0;
2498   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2499   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2500   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2501   DAInt neigh00(tmp0);
2502   DAInt neighI00(tmp1);
2503
2504   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2505   int seed = 0, nIter = 0;
2506   int nIterMax = nCells2+1; // Safety net for the loop
2507   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2508   hitCells->fillWithValue(-1);
2509   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2510   cellsToModifyConn0_torenum->alloc(0,1);
2511   while (nIter < nIterMax)
2512     {
2513       DAInt t = hitCells->getIdsEqual(-1);
2514       if (!t->getNumberOfTuples())
2515         break;
2516       // Connex zone without the crack (to compute the next seed really)
2517       int dnu;
2518       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2519       int cnt = 0;
2520       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2521         hitCells->setIJ(*ptr,0,1);
2522       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2523       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2524       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2525       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2526       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2527       DAInt nonHitCells = hitCells->getIdsEqual(-1);
2528       DAInt intersec = nonHitCells->buildIntersection(comple);
2529       if (intersec->getNumberOfTuples())
2530         { seed = intersec->getIJ(0,0); }
2531       else
2532         { break; }
2533       nIter++;
2534     }
2535   if (nIter >= nIterMax)
2536     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2537
2538   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2539   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2540   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2541   //
2542   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2543   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2544   nodeIdsToDuplicate=s3.retn();
2545 }
2546
2547 /*!
2548  * This method operates a modification of the connectivity and coords in \b this.
2549  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2550  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2551  * 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
2552  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2553  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2554  * 
2555  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2556  * 
2557  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2558  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2559  */
2560 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2561 {
2562   int nbOfNodes=getNumberOfNodes();
2563   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2564   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2565 }
2566
2567 /*!
2568  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2569  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2570  *
2571  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2572  *
2573  * \sa renumberNodesInConn
2574  */
2575 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
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             node+=offset;
2588           }
2589       }
2590   _nodal_connec->declareAsNew();
2591   updateTime();
2592 }
2593
2594 /*!
2595  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2596  *  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
2597  *  of a big mesh.
2598  */
2599 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2600 {
2601   checkConnectivityFullyDefined();
2602   int *conn(getNodalConnectivity()->getPointer());
2603   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2604   int nbOfCells(getNumberOfCells());
2605   for(int i=0;i<nbOfCells;i++)
2606     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2607       {
2608         int& node=conn[iconn];
2609         if(node>=0)//avoid polyhedron separator
2610           {
2611             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2612             if(it!=newNodeNumbersO2N.end())
2613               {
2614                 node=(*it).second;
2615               }
2616             else
2617               {
2618                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2619                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2620               }
2621           }
2622       }
2623   _nodal_connec->declareAsNew();
2624   updateTime();
2625 }
2626
2627 /*!
2628  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2629  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2630  * This method is a generalization of shiftNodeNumbersInConn().
2631  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2632  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2633  *         this->getNumberOfNodes(), in "Old to New" mode. 
2634  *         See \ref numbering for more info on renumbering modes.
2635  *  \throw If the nodal connectivity of cells is not defined.
2636  *
2637  *  \if ENABLE_EXAMPLES
2638  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2639  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2640  *  \endif
2641  */
2642 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2643 {
2644   checkConnectivityFullyDefined();
2645   int *conn=getNodalConnectivity()->getPointer();
2646   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2647   int nbOfCells(getNumberOfCells());
2648   for(int i=0;i<nbOfCells;i++)
2649     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2650       {
2651         int& node=conn[iconn];
2652         if(node>=0)//avoid polyhedron separator
2653           {
2654             node=newNodeNumbersO2N[node];
2655           }
2656       }
2657   _nodal_connec->declareAsNew();
2658   updateTime();
2659 }
2660
2661 /*!
2662  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2663  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2664  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2665  * 
2666  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2667  */
2668 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2669 {
2670   checkConnectivityFullyDefined();
2671   int *conn=getNodalConnectivity()->getPointer();
2672   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2673   int nbOfCells=getNumberOfCells();
2674   for(int i=0;i<nbOfCells;i++)
2675     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2676       {
2677         int& node=conn[iconn];
2678         if(node>=0)//avoid polyhedron separator
2679           {
2680             node+=delta;
2681           }
2682       }
2683   _nodal_connec->declareAsNew();
2684   updateTime();
2685 }
2686
2687 /*!
2688  * This method operates a modification of the connectivity in \b this.
2689  * 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.
2690  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2691  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2692  * 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
2693  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2694  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2695  * 
2696  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2697  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2698  * 
2699  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2700  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2701  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2702  */
2703 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2704 {
2705   checkConnectivityFullyDefined();
2706   std::map<int,int> m;
2707   int val=offset;
2708   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2709     m[*work]=val;
2710   int *conn=getNodalConnectivity()->getPointer();
2711   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2712   int nbOfCells=getNumberOfCells();
2713   for(int i=0;i<nbOfCells;i++)
2714     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2715       {
2716         int& node=conn[iconn];
2717         if(node>=0)//avoid polyhedron separator
2718           {
2719             std::map<int,int>::iterator it=m.find(node);
2720             if(it!=m.end())
2721               node=(*it).second;
2722           }
2723       }
2724   updateTime();
2725 }
2726
2727 /*!
2728  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2729  *
2730  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2731  * After the call of this method the number of cells remains the same as before.
2732  *
2733  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2734  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2735  * be strictly in [0;this->getNumberOfCells()).
2736  *
2737  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2738  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2739  * should be contained in[0;this->getNumberOfCells()).
2740  * 
2741  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2742  * \param check
2743  */
2744 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2745 {
2746   checkConnectivityFullyDefined();
2747   int nbCells=getNumberOfCells();
2748   const int *array=old2NewBg;
2749   if(check)
2750     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2751   //
2752   const int *conn=_nodal_connec->getConstPointer();
2753   const int *connI=_nodal_connec_index->getConstPointer();
2754   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2755   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2756   const int *n2oPtr=n2o->begin();
2757   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2758   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2759   newConn->copyStringInfoFrom(*_nodal_connec);
2760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2761   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2762   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2763   //
2764   int *newC=newConn->getPointer();
2765   int *newCI=newConnI->getPointer();
2766   int loc=0;
2767   newCI[0]=loc;
2768   for(int i=0;i<nbCells;i++)
2769     {
2770       int pos=n2oPtr[i];
2771       int nbOfElts=connI[pos+1]-connI[pos];
2772       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2773       loc+=nbOfElts;
2774       newCI[i+1]=loc;
2775     }
2776   //
2777   setConnectivity(newConn,newConnI);
2778   if(check)
2779     free(const_cast<int *>(array));
2780 }
2781
2782 /*!
2783  * Finds cells whose bounding boxes intersect a given bounding box.
2784  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2785  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2786  *         zMax (if in 3D). 
2787  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2788  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2789  *         extent of the bounding box of cell to produce an addition to this bounding box.
2790  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2791  *         cells. The caller is to delete this array using decrRef() as it is no more
2792  *         needed. 
2793  *  \throw If the coordinates array is not set.
2794  *  \throw If the nodal connectivity of cells is not defined.
2795  *
2796  *  \if ENABLE_EXAMPLES
2797  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2798  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2799  *  \endif
2800  */
2801 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2802 {
2803   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2804   if(getMeshDimension()==-1)
2805     {
2806       elems->pushBackSilent(0);
2807       return elems.retn();
2808     }
2809   int dim=getSpaceDimension();
2810   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2811   const int* conn      = getNodalConnectivity()->getConstPointer();
2812   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2813   const double* coords = getCoords()->getConstPointer();
2814   int nbOfCells=getNumberOfCells();
2815   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2816     {
2817       for (int i=0; i<dim; i++)
2818         {
2819           elem_bb[i*2]=std::numeric_limits<double>::max();
2820           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2821         }
2822
2823       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2824         {
2825           int node= conn[inode];
2826           if(node>=0)//avoid polyhedron separator
2827             {
2828               for (int idim=0; idim<dim; idim++)
2829                 {
2830                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2831                     {
2832                       elem_bb[idim*2] = coords[node*dim+idim] ;
2833                     }
2834                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2835                     {
2836                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2837                     }
2838                 }
2839             }
2840         }
2841       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2842         elems->pushBackSilent(ielem);
2843     }
2844   return elems.retn();
2845 }
2846
2847 /*!
2848  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2849  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2850  * added in 'elems' parameter.
2851  */
2852 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2853 {
2854   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2855   if(getMeshDimension()==-1)
2856     {
2857       elems->pushBackSilent(0);
2858       return elems.retn();
2859     }
2860   int dim=getSpaceDimension();
2861   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2862   const int* conn      = getNodalConnectivity()->getConstPointer();
2863   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2864   const double* coords = getCoords()->getConstPointer();
2865   int nbOfCells=getNumberOfCells();
2866   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2867     {
2868       for (int i=0; i<dim; i++)
2869         {
2870           elem_bb[i*2]=std::numeric_limits<double>::max();
2871           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2872         }
2873
2874       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2875         {
2876           int node= conn[inode];
2877           if(node>=0)//avoid polyhedron separator
2878             {
2879               for (int idim=0; idim<dim; idim++)
2880                 {
2881                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2882                     {
2883                       elem_bb[idim*2] = coords[node*dim+idim] ;
2884                     }
2885                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2886                     {
2887                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2888                     }
2889                 }
2890             }
2891         }
2892       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2893         elems->pushBackSilent(ielem);
2894     }
2895   return elems.retn();
2896 }
2897
2898 /*!
2899  * Returns a type of a cell by its id.
2900  *  \param [in] cellId - the id of the cell of interest.
2901  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2902  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2903  */
2904 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2905 {
2906   const int *ptI=_nodal_connec_index->getConstPointer();
2907   const int *pt=_nodal_connec->getConstPointer();
2908   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2909     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2910   else
2911     {
2912       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2913       throw INTERP_KERNEL::Exception(oss.str().c_str());
2914     }
2915 }
2916
2917 /*!
2918  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2919  * This method does not throw exception if geometric type \a type is not in \a this.
2920  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2921  * The coordinates array is not considered here.
2922  *
2923  * \param [in] type the geometric type
2924  * \return cell ids in this having geometric type \a type.
2925  */
2926 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2927 {
2928
2929   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2930   ret->alloc(0,1);
2931   checkConnectivityFullyDefined();
2932   int nbCells=getNumberOfCells();
2933   int mdim=getMeshDimension();
2934   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2935   if(mdim!=(int)cm.getDimension())
2936     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2937   const int *ptI=_nodal_connec_index->getConstPointer();
2938   const int *pt=_nodal_connec->getConstPointer();
2939   for(int i=0;i<nbCells;i++)
2940     {
2941       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2942         ret->pushBackSilent(i);
2943     }
2944   return ret.retn();
2945 }
2946
2947 /*!
2948  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2949  */
2950 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2951 {
2952   const int *ptI=_nodal_connec_index->getConstPointer();
2953   const int *pt=_nodal_connec->getConstPointer();
2954   int nbOfCells=getNumberOfCells();
2955   int ret=0;
2956   for(int i=0;i<nbOfCells;i++)
2957     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2958       ret++;
2959   return ret;
2960 }
2961
2962 /*!
2963  * Returns the nodal connectivity of a given cell.
2964  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2965  * all returned node ids can be used in getCoordinatesOfNode().
2966  *  \param [in] cellId - an id of the cell of interest.
2967  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2968  *         cleared before the appending.
2969  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2970  */
2971 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2972 {
2973   const int *ptI=_nodal_connec_index->getConstPointer();
2974   const int *pt=_nodal_connec->getConstPointer();
2975   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2976     if(*w>=0)
2977       conn.push_back(*w);
2978 }
2979
2980 std::string MEDCouplingUMesh::simpleRepr() const
2981 {
2982   static const char msg0[]="No coordinates specified !";
2983   std::ostringstream ret;
2984   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2985   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2986   int tmpp1,tmpp2;
2987   double tt=getTime(tmpp1,tmpp2);
2988   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2989   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2990   if(_mesh_dim>=-1)
2991     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2992   else
2993     { ret << " Mesh dimension has not been set or is invalid !"; }
2994   if(_coords!=0)
2995     {
2996       const int spaceDim=getSpaceDimension();
2997       ret << spaceDim << "\nInfo attached on space dimension : ";
2998       for(int i=0;i<spaceDim;i++)
2999         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3000       ret << "\n";
3001     }
3002   else
3003     ret << msg0 << "\n";
3004   ret << "Number of nodes : ";
3005   if(_coords!=0)
3006     ret << getNumberOfNodes() << "\n";
3007   else
3008     ret << msg0 << "\n";
3009   ret << "Number of cells : ";
3010   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3011     ret << getNumberOfCells() << "\n";
3012   else
3013     ret << "No connectivity specified !" << "\n";
3014   ret << "Cell types present : ";
3015   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3016     {
3017       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3018       ret << cm.getRepr() << " ";
3019     }
3020   ret << "\n";
3021   return ret.str();
3022 }
3023
3024 std::string MEDCouplingUMesh::advancedRepr() const
3025 {
3026   std::ostringstream ret;
3027   ret << simpleRepr();
3028   ret << "\nCoordinates array : \n___________________\n\n";
3029   if(_coords)
3030     _coords->reprWithoutNameStream(ret);
3031   else
3032     ret << "No array set !\n";
3033   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3034   reprConnectivityOfThisLL(ret);
3035   return ret.str();
3036 }
3037
3038 /*!
3039  * This method returns a C++ code that is a dump of \a this.
3040  * This method will throw if this is not fully defined.
3041  */
3042 std::string MEDCouplingUMesh::cppRepr() const
3043 {
3044   static const char coordsName[]="coords";
3045   static const char connName[]="conn";
3046   static const char connIName[]="connI";
3047   checkFullyDefined();
3048   std::ostringstream ret; ret << "// coordinates" << std::endl;
3049   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3050   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3051   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3052   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3053   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3054   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3055   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3056   return ret.str();
3057 }
3058
3059 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3060 {
3061   std::ostringstream ret;
3062   reprConnectivityOfThisLL(ret);
3063   return ret.str();
3064 }
3065
3066 /*!
3067  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3068  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3069  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3070  * some algos).
3071  * 
3072  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3073  * 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
3074  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3075  */
3076 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3077 {
3078   int mdim=getMeshDimension();
3079   if(mdim<0)
3080     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3081   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3082   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3083   bool needToCpyCT=true;
3084   if(!_nodal_connec)
3085     {
3086       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3087       needToCpyCT=false;
3088     }
3089   else
3090     {
3091       tmp1=_nodal_connec;
3092       tmp1->incrRef();
3093     }
3094   if(!_nodal_connec_index)
3095     {
3096       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3097       needToCpyCT=false;
3098     }
3099   else
3100     {
3101       tmp2=_nodal_connec_index;
3102       tmp2->incrRef();
3103     }
3104   ret->setConnectivity(tmp1,tmp2,false);
3105   if(needToCpyCT)
3106     ret->_types=_types;
3107   if(!_coords)
3108     {
3109       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3110       ret->setCoords(coords);
3111     }
3112   else
3113     ret->setCoords(_coords);
3114   return ret.retn();
3115 }
3116
3117 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3118 {
3119   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3120     {
3121       int nbOfCells=getNumberOfCells();
3122       const int *c=_nodal_connec->getConstPointer();
3123       const int *ci=_nodal_connec_index->getConstPointer();
3124       for(int i=0;i<nbOfCells;i++)
3125         {
3126           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3127           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3128           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3129           stream << "\n";
3130         }
3131     }
3132   else
3133     stream << "Connectivity not defined !\n";
3134 }
3135
3136 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3137 {
3138   const int *ptI=_nodal_connec_index->getConstPointer();
3139   const int *pt=_nodal_connec->getConstPointer();
3140   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3141     return ptI[cellId+1]-ptI[cellId]-1;
3142   else
3143     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3144 }
3145
3146 /*!
3147  * Returns types of cells of the specified part of \a this mesh.
3148  * This method avoids computing sub-mesh explicitely to get its types.
3149  *  \param [in] begin - an array of cell ids of interest.
3150  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3151  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3152  *         describing the cell types. 
3153  *  \throw If the coordinates array is not set.
3154  *  \throw If the nodal connectivity of cells is not defined.
3155  *  \sa getAllGeoTypes()
3156  */
3157 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3158 {
3159   checkFullyDefined();
3160   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3161   const int *conn=_nodal_connec->getConstPointer();
3162   const int *connIndex=_nodal_connec_index->getConstPointer();
3163   for(const int *w=begin;w!=end;w++)
3164     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3165   return ret;
3166 }
3167
3168 /*!
3169  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3170  * Optionally updates
3171  * a set of types of cells constituting \a this mesh. 
3172  * This method is for advanced users having prepared their connectivity before. For
3173  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3174  *  \param [in] conn - the nodal connectivity array. 
3175  *  \param [in] connIndex - the nodal connectivity index array.
3176  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3177  *         mesh is updated.
3178  */
3179 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3180 {
3181   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3182   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3183   if(isComputingTypes)
3184     computeTypes();
3185   declareAsNew();
3186 }
3187
3188 /*!
3189  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3190  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3191  */
3192 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3193     _nodal_connec(0),_nodal_connec_index(0),
3194     _types(other._types)
3195 {
3196   if(other._nodal_connec)
3197     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3198   if(other._nodal_connec_index)
3199     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3200 }
3201
3202 MEDCouplingUMesh::~MEDCouplingUMesh()
3203 {
3204   if(_nodal_connec)
3205     _nodal_connec->decrRef();
3206   if(_nodal_connec_index)
3207     _nodal_connec_index->decrRef();
3208 }
3209
3210 /*!
3211  * Recomputes a set of cell types of \a this mesh. For more info see
3212  * \ref MEDCouplingUMeshNodalConnectivity.
3213  */
3214 void MEDCouplingUMesh::computeTypes()
3215 {
3216   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3217 }
3218
3219 /*!
3220  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3221  */
3222 void MEDCouplingUMesh::checkFullyDefined() const
3223 {
3224   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3225     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3226 }
3227
3228 /*!
3229  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3230  */
3231 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3232 {
3233   if(!_nodal_connec_index || !_nodal_connec)
3234     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3235 }
3236
3237 /*!
3238  * Returns a number of cells constituting \a this mesh. 
3239  *  \return int - the number of cells in \a this mesh.
3240  *  \throw If the nodal connectivity of cells is not defined.
3241  */
3242 int MEDCouplingUMesh::getNumberOfCells() const
3243
3244   if(_nodal_connec_index)
3245     return _nodal_connec_index->getNumberOfTuples()-1;
3246   else
3247     if(_mesh_dim==-1)
3248       return 1;
3249     else
3250       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3251 }
3252
3253 /*!
3254  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3255  * mesh. For more info see \ref meshes.
3256  *  \return int - the dimension of \a this mesh.
3257  *  \throw If the mesh dimension is not defined using setMeshDimension().
3258  */
3259 int MEDCouplingUMesh::getMeshDimension() const
3260 {
3261   if(_mesh_dim<-1)
3262     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3263   return _mesh_dim;
3264 }
3265
3266 /*!
3267  * Returns a length of the nodal connectivity array.
3268  * This method is for test reason. Normally the integer returned is not useable by
3269  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3270  *  \return int - the length of the nodal connectivity array.
3271  */
3272 int MEDCouplingUMesh::getMeshLength() const
3273 {
3274   return _nodal_connec->getNbOfElems();
3275 }
3276
3277 /*!
3278  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3279  */
3280 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3281 {
3282   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3283   tinyInfo.push_back(getMeshDimension());
3284   tinyInfo.push_back(getNumberOfCells());
3285   if(_nodal_connec)
3286     tinyInfo.push_back(getMeshLength());
3287   else
3288     tinyInfo.push_back(-1);
3289 }
3290
3291 /*!
3292  * First step of unserialization process.
3293  */
3294 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3295 {
3296   return tinyInfo[6]<=0;
3297 }
3298
3299 /*!
3300  * Second step of serialization process.
3301  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3302  * \param a1
3303  * \param a2
3304  * \param littleStrings
3305  */
3306 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3307 {
3308   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3309   if(tinyInfo[5]!=-1)
3310     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3311 }
3312
3313 /*!
3314  * Third and final step of serialization process.
3315  */
3316 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3317 {
3318   MEDCouplingPointSet::serialize(a1,a2);
3319   if(getMeshDimension()>-1)
3320     {
3321       a1=DataArrayInt::New();
3322       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3323       int *ptA1=a1->getPointer();
3324       const int *conn=getNodalConnectivity()->getConstPointer();
3325       const int *index=getNodalConnectivityIndex()->getConstPointer();
3326       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3327       std::copy(conn,conn+getMeshLength(),ptA1);
3328     }
3329   else
3330     a1=0;
3331 }
3332
3333 /*!
3334  * Second and final unserialization process.
3335  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3336  */
3337 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3338 {
3339   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3340   setMeshDimension(tinyInfo[5]);
3341   if(tinyInfo[7]!=-1)
3342     {
3343       // Connectivity
3344       const int *recvBuffer=a1->getConstPointer();
3345       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3346       myConnecIndex->alloc(tinyInfo[6]+1,1);
3347       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3348       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3349       myConnec->alloc(tinyInfo[7],1);
3350       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3351       setConnectivity(myConnec, myConnecIndex);
3352     }
3353 }
3354
3355 /*!
3356  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3357  * CellIds are given using range specified by a start an end and step.
3358  */
3359 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3360 {
3361   checkFullyDefined();
3362   int ncell=getNumberOfCells();
3363   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3364   ret->_mesh_dim=_mesh_dim;
3365   ret->setCoords(_coords);
3366   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3367   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3368   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3369   int work=start;
3370   const int *conn=_nodal_connec->getConstPointer();
3371   const int *connIndex=_nodal_connec_index->getConstPointer();
3372   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3373     {
3374       if(work>=0 && work<ncell)
3375         {
3376           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3377         }
3378       else
3379         {
3380           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3381           throw INTERP_KERNEL::Exception(oss.str().c_str());
3382         }
3383     }
3384   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3385   int *newConnPtr=newConn->getPointer();
3386   std::set<INTERP_KERNEL::NormalizedCellType> types;
3387   work=start;
3388   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3389     {
3390       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3391       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3392     }
3393   ret->setConnectivity(newConn,newConnI,false);
3394   ret->_types=types;
3395   ret->copyTinyInfoFrom(this);
3396   return ret.retn();
3397 }
3398
3399 /*!
3400  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3401  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3402  * The return newly allocated mesh will share the same coordinates as \a this.
3403  */
3404 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3405 {
3406   checkConnectivityFullyDefined();
3407   int ncell=getNumberOfCells();
3408   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3409   ret->_mesh_dim=_mesh_dim;
3410   ret->setCoords(_coords);
3411   std::size_t nbOfElemsRet=std::distance(begin,end);
3412   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3413   connIndexRet[0]=0;
3414   const int *conn=_nodal_connec->getConstPointer();
3415   const int *connIndex=_nodal_connec_index->getConstPointer();
3416   int newNbring=0;
3417   for(const int *work=begin;work!=end;work++,newNbring++)
3418     {
3419       if(*work>=0 && *work<ncell)
3420         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3421       else
3422         {
3423           free(connIndexRet);
3424           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3425           throw INTERP_KERNEL::Exception(oss.str().c_str());
3426         }
3427     }
3428   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3429   int *connRetWork=connRet;
3430   std::set<INTERP_KERNEL::NormalizedCellType> types;
3431   for(const int *work=begin;work!=end;work++)
3432     {
3433       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3434       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3435     }
3436   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3437   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3438   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3439   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3440   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3441   ret->_types=types;
3442   ret->copyTinyInfoFrom(this);
3443   return ret.retn();
3444 }
3445
3446 /*!
3447  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3448  * mesh.<br>
3449  * For 1D cells, the returned field contains lengths.<br>
3450  * For 2D cells, the returned field contains areas.<br>
3451  * For 3D cells, the returned field contains volumes.
3452  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3453  *         orientation, i.e. the volume is always positive.
3454  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3455  *         and one time . The caller is to delete this field using decrRef() as it is no
3456  *         more needed.
3457  */
3458 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3459 {
3460   std::string name="MeasureOfMesh_";
3461   name+=getName();
3462   int nbelem=getNumberOfCells();
3463   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3464   field->setName(name);
3465   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3466   array->alloc(nbelem,1);
3467   double *area_vol=array->getPointer();
3468   field->setArray(array) ; array=0;
3469   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3470   field->synchronizeTimeWithMesh();
3471   if(getMeshDimension()!=-1)
3472     {
3473       int ipt;
3474       INTERP_KERNEL::NormalizedCellType type;
3475       int dim_space=getSpaceDimension();
3476       const double *coords=getCoords()->getConstPointer();
3477       const int *connec=getNodalConnectivity()->getConstPointer();
3478       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3479       for(int iel=0;iel<nbelem;iel++)
3480         {
3481           ipt=connec_index[iel];
3482           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3483           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);
3484         }
3485       if(isAbs)
3486         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3487     }
3488   else
3489     {
3490       area_vol[0]=std::numeric_limits<double>::max();
3491     }
3492   return field.retn();
3493 }
3494
3495 /*!
3496  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3497  * mesh.<br>
3498  * For 1D cells, the returned array contains lengths.<br>
3499  * For 2D cells, the returned array contains areas.<br>
3500  * For 3D cells, the returned array contains volumes.
3501  * This method avoids building explicitly a part of \a this mesh to perform the work.
3502  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3503  *         orientation, i.e. the volume is always positive.
3504  *  \param [in] begin - an array of cell ids of interest.
3505  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3506  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3507  *          delete this array using decrRef() as it is no more needed.
3508  * 
3509  *  \if ENABLE_EXAMPLES
3510  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3511  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3512  *  \endif
3513  *  \sa getMeasureField()
3514  */
3515 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3516 {
3517   std::string name="PartMeasureOfMesh_";
3518   name+=getName();
3519   int nbelem=(int)std::distance(begin,end);
3520   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3521   array->setName(name);
3522   array->alloc(nbelem,1);
3523   double *area_vol=array->getPointer();
3524   if(getMeshDimension()!=-1)
3525     {
3526       int ipt;
3527       INTERP_KERNEL::NormalizedCellType type;
3528       int dim_space=getSpaceDimension();
3529       const double *coords=getCoords()->getConstPointer();
3530       const int *connec=getNodalConnectivity()->getConstPointer();
3531       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3532       for(const int *iel=begin;iel!=end;iel++)
3533         {
3534           ipt=connec_index[*iel];
3535           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3536           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3537         }
3538       if(isAbs)
3539         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3540     }
3541   else
3542     {
3543       area_vol[0]=std::numeric_limits<double>::max();
3544     }
3545   return array.retn();
3546 }
3547
3548 /*!
3549  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3550  * \a this one. The returned field contains the dual cell volume for each corresponding
3551  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3552  *  the dual mesh in P1 sens of \a this.<br>
3553  * For 1D cells, the returned field contains lengths.<br>
3554  * For 2D cells, the returned field contains areas.<br>
3555  * For 3D cells, the returned field contains volumes.
3556  * This method is useful to check "P1*" conservative interpolators.
3557  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3558  *         orientation, i.e. the volume is always positive.
3559  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3560  *          nodes and one time. The caller is to delete this array using decrRef() as
3561  *          it is no more needed.
3562  */
3563 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3564 {
3565   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3566   std::string name="MeasureOnNodeOfMesh_";
3567   name+=getName();
3568   int nbNodes=getNumberOfNodes();
3569   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3570   double cst=1./((double)getMeshDimension()+1.);
3571   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3572   array->alloc(nbNodes,1);
3573   double *valsToFill=array->getPointer();
3574   std::fill(valsToFill,valsToFill+nbNodes,0.);
3575   const double *values=tmp->getArray()->getConstPointer();
3576   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3577   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3578   getReverseNodalConnectivity(da,daInd);
3579   const int *daPtr=da->getConstPointer();
3580   const int *daIPtr=daInd->getConstPointer();
3581   for(int i=0;i<nbNodes;i++)
3582     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3583       valsToFill[i]+=cst*values[*cell];
3584   ret->setMesh(this);
3585   ret->setArray(array);
3586   return ret.retn();
3587 }
3588
3589 /*!
3590  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3591  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3592  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3593  * and are normalized.
3594  * <br> \a this can be either 
3595  * - a  2D mesh in 2D or 3D space or 
3596  * - an 1D mesh in 2D space.
3597  * 
3598  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3599  *          cells and one time. The caller is to delete this field using decrRef() as
3600  *          it is no more needed.
3601  *  \throw If the nodal connectivity of cells is not defined.
3602  *  \throw If the coordinates array is not set.
3603  *  \throw If the mesh dimension is not set.
3604  *  \throw If the mesh and space dimension is not as specified above.
3605  */
3606 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3607 {
3608   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3609     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3610   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3611   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3612   int nbOfCells=getNumberOfCells();
3613   int nbComp=getMeshDimension()+1;
3614   array->alloc(nbOfCells,nbComp);
3615   double *vals=array->getPointer();
3616   const int *connI=_nodal_connec_index->getConstPointer();
3617   const int *conn=_nodal_connec->getConstPointer();
3618   const double *coords=_coords->getConstPointer();
3619   if(getMeshDimension()==2)
3620     {
3621       if(getSpaceDimension()==3)
3622         {
3623           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3624           const double *locPtr=loc->getConstPointer();
3625           for(int i=0;i<nbOfCells;i++,vals+=3)
3626             {
3627               int offset=connI[i];
3628               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3629               double n=INTERP_KERNEL::norm<3>(vals);
3630               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3631             }
3632         }
3633       else
3634         {
3635           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3636           const double *isAbsPtr=isAbs->getArray()->begin();
3637           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3638             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3639         }
3640     }
3641   else//meshdimension==1
3642     {
3643       double tmp[2];
3644       for(int i=0;i<nbOfCells;i++)
3645         {
3646           int offset=connI[i];
3647           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3648           double n=INTERP_KERNEL::norm<2>(tmp);
3649           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3650           *vals++=-tmp[1];
3651           *vals++=tmp[0];
3652         }
3653     }
3654   ret->setArray(array);
3655   ret->setMesh(this);
3656   ret->synchronizeTimeWithSupport();
3657   return ret.retn();
3658 }
3659
3660 /*!
3661  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3662  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3663  * and are normalized.
3664  * <br> \a this can be either 
3665  * - a  2D mesh in 2D or 3D space or 
3666  * - an 1D mesh in 2D space.
3667  * 
3668  * This method avoids building explicitly a part of \a this mesh to perform the work.
3669  *  \param [in] begin - an array of cell ids of interest.
3670  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3671  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3672  *          cells and one time. The caller is to delete this field using decrRef() as
3673  *          it is no more needed.
3674  *  \throw If the nodal connectivity of cells is not defined.
3675  *  \throw If the coordinates array is not set.
3676  *  \throw If the mesh dimension is not set.
3677  *  \throw If the mesh and space dimension is not as specified above.
3678  *  \sa buildOrthogonalField()
3679  *
3680  *  \if ENABLE_EXAMPLES
3681  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3682  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3683  *  \endif
3684  */
3685 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3686 {
3687   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3688     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3689   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3690   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3691   std::size_t nbelems=std::distance(begin,end);
3692   int nbComp=getMeshDimension()+1;
3693   array->alloc((int)nbelems,nbComp);
3694   double *vals=array->getPointer();
3695   const int *connI=_nodal_connec_index->getConstPointer();
3696   const int *conn=_nodal_connec->getConstPointer();
3697   const double *coords=_coords->getConstPointer();
3698   if(getMeshDimension()==2)
3699     {
3700       if(getSpaceDimension()==3)
3701         {
3702           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3703           const double *locPtr=loc->getConstPointer();
3704           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3705             {
3706               int offset=connI[*i];
3707               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3708               double n=INTERP_KERNEL::norm<3>(vals);
3709               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3710             }
3711         }
3712       else
3713         {
3714           for(std::size_t i=0;i<nbelems;i++)
3715             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3716         }
3717     }
3718   else//meshdimension==1
3719     {
3720       double tmp[2];
3721       for(const int *i=begin;i!=end;i++)
3722         {
3723           int offset=connI[*i];
3724           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3725           double n=INTERP_KERNEL::norm<2>(tmp);
3726           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3727           *vals++=-tmp[1];
3728           *vals++=tmp[0];
3729         }
3730     }
3731   ret->setArray(array);
3732   ret->setMesh(this);
3733   ret->synchronizeTimeWithSupport();
3734   return ret.retn();
3735 }
3736
3737 /*!
3738  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3739  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3740  * and are \b not normalized.
3741  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3742  *          cells and one time. The caller is to delete this field using decrRef() as
3743  *          it is no more needed.
3744  *  \throw If the nodal connectivity of cells is not defined.
3745  *  \throw If the coordinates array is not set.
3746  *  \throw If \a this->getMeshDimension() != 1.
3747  *  \throw If \a this mesh includes cells of type other than SEG2.
3748  */
3749 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3750 {
3751   if(getMeshDimension()!=1)
3752     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3753   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3754     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3755   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3756   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3757   int nbOfCells=getNumberOfCells();
3758   int spaceDim=getSpaceDimension();
3759   array->alloc(nbOfCells,spaceDim);
3760   double *pt=array->getPointer();
3761   const double *coo=getCoords()->getConstPointer();
3762   std::vector<int> conn;
3763   conn.reserve(2);
3764   for(int i=0;i<nbOfCells;i++)
3765     {
3766       conn.resize(0);
3767       getNodeIdsOfCell(i,conn);
3768       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3769     }
3770   ret->setArray(array);
3771   ret->setMesh(this);
3772   ret->synchronizeTimeWithSupport();
3773   return ret.retn();
3774 }
3775
3776 /*!
3777  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3778  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3779  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3780  * from. If a result face is shared by two 3D cells, then the face in included twice in
3781  * the result mesh.
3782  *  \param [in] origin - 3 components of a point defining location of the plane.
3783  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3784  *         must be greater than 1e-6.
3785  *  \param [in] eps - half-thickness of the plane.
3786  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3787  *         producing correspondent 2D cells. The caller is to delete this array
3788  *         using decrRef() as it is no more needed.
3789  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3790  *         not share the node coordinates array with \a this mesh. The caller is to
3791  *         delete this mesh using decrRef() as it is no more needed.  
3792  *  \throw If the coordinates array is not set.
3793  *  \throw If the nodal connectivity of cells is not defined.
3794  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3795  *  \throw If magnitude of \a vec is less than 1e-6.
3796  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3797  *  \throw If \a this includes quadratic cells.
3798  */
3799 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3800 {
3801   checkFullyDefined();
3802   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3803     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3804   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3805   if(candidates->empty())
3806     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3807   std::vector<int> nodes;
3808   DataArrayInt *cellIds1D=0;
3809   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3810   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3811   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3812   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3814   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3815   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3816   revDesc2=0; revDescIndx2=0;
3817   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3818   revDesc1=0; revDescIndx1=0;
3819   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3821   //
3822   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3823   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3824     cut3DCurve[*it]=-1;
3825   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3826   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3827   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3828                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3829                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3831   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3832   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3833   if(cellIds2->empty())
3834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3835   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3836   ret->setCoords(mDesc1->getCoords());
3837   ret->setConnectivity(conn,connI,true);
3838   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3839   return ret.retn();
3840 }
3841
3842 /*!
3843  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3844 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
3845 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3846 the result mesh.
3847  *  \param [in] origin - 3 components of a point defining location of the plane.
3848  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3849  *         must be greater than 1e-6.
3850  *  \param [in] eps - half-thickness of the plane.
3851  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3852  *         producing correspondent segments. The caller is to delete this array
3853  *         using decrRef() as it is no more needed.
3854  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3855  *         mesh in 3D space. This mesh does not share the node coordinates array with
3856  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3857  *         no more needed. 
3858  *  \throw If the coordinates array is not set.
3859  *  \throw If the nodal connectivity of cells is not defined.
3860  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3861  *  \throw If magnitude of \a vec is less than 1e-6.
3862  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3863  *  \throw If \a this includes quadratic cells.
3864  */
3865 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3866 {
3867   checkFullyDefined();
3868   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3869     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3870   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3871   if(candidates->empty())
3872     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3873   std::vector<int> nodes;
3874   DataArrayInt *cellIds1D=0;
3875   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3876   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3879   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3881   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3882   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3883   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3884   //
3885   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3886   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3887     cut3DCurve[*it]=-1;
3888   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3889   int ncellsSub=subMesh->getNumberOfCells();
3890   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3891   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3892                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3893                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3894   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3895   conn->alloc(0,1);
3896   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3897   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3898   for(int i=0;i<ncellsSub;i++)
3899     {
3900       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3901         {
3902           if(cut3DSurf[i].first!=-2)
3903             {
3904               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3905               connI->pushBackSilent(conn->getNumberOfTuples());
3906               cellIds2->pushBackSilent(i);
3907             }
3908           else
3909             {
3910               int cellId3DSurf=cut3DSurf[i].second;
3911               int offset=nodalI[cellId3DSurf]+1;
3912               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3913               for(int j=0;j<nbOfEdges;j++)
3914                 {
3915                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3916                   connI->pushBackSilent(conn->getNumberOfTuples());
3917                   cellIds2->pushBackSilent(cellId3DSurf);
3918                 }
3919             }
3920         }
3921     }
3922   if(cellIds2->empty())
3923     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3924   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3925   ret->setCoords(mDesc1->getCoords());
3926   ret->setConnectivity(conn,connI,true);
3927   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3928   return ret.retn();
3929 }
3930
3931 /*!
3932  * Finds cells whose bounding boxes intersect a given plane.
3933  *  \param [in] origin - 3 components of a point defining location of the plane.
3934  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3935  *         must be greater than 1e-6.
3936  *  \param [in] eps - half-thickness of the plane.
3937  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3938  *         cells. The caller is to delete this array using decrRef() as it is no more
3939  *         needed.
3940  *  \throw If the coordinates array is not set.
3941  *  \throw If the nodal connectivity of cells is not defined.
3942  *  \throw If \a this->getSpaceDimension() != 3.
3943  *  \throw If magnitude of \a vec is less than 1e-6.
3944  *  \sa buildSlice3D()
3945  */
3946 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3947 {
3948   checkFullyDefined();
3949   if(getSpaceDimension()!=3)
3950     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3951   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3952   if(normm<1e-6)
3953     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3954   double vec2[3];
3955   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3956   double angle=acos(vec[2]/normm);
3957   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3958   double bbox[6];
3959   if(angle>eps)
3960     {
3961       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3962       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3963       if(normm2/normm>1e-6)
3964         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3965       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3966       mw->setCoords(coo);
3967       mw->getBoundingBox(bbox);
3968       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3969       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3970     }
3971   else
3972     {
3973       getBoundingBox(bbox);
3974       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3975       cellIds=getCellsInBoundingBox(bbox,eps);
3976     }
3977   return cellIds.retn();
3978 }
3979
3980 /*!
3981  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3982  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3983  * No consideration of coordinate is done by this method.
3984  * 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)
3985  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3986  */
3987 bool MEDCouplingUMesh::isContiguous1D() const
3988 {
3989   if(getMeshDimension()!=1)
3990     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3991   int nbCells=getNumberOfCells();
3992   if(nbCells<1)
3993     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3994   const int *connI=_nodal_connec_index->getConstPointer();
3995   const int *conn=_nodal_connec->getConstPointer();
3996   int ref=conn[connI[0]+2];
3997   for(int i=1;i<nbCells;i++)
3998     {
3999       if(conn[connI[i]+1]!=ref)
4000         return false;
4001       ref=conn[connI[i]+2];
4002     }
4003   return true;
4004 }
4005
4006 /*!
4007  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4008  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4009  * \param pt reference point of the line
4010  * \param v normalized director vector of the line
4011  * \param eps max precision before throwing an exception
4012  * \param res output of size this->getNumberOfCells
4013  */
4014 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4015 {
4016   if(getMeshDimension()!=1)
4017     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4018   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4019     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4020   if(getSpaceDimension()!=3)
4021     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4022   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4023   const double *fPtr=f->getArray()->getConstPointer();
4024   double tmp[3];
4025   for(int i=0;i<getNumberOfCells();i++)
4026     {
4027       const double *tmp1=fPtr+3*i;
4028       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4029       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4030       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4031       double n1=INTERP_KERNEL::norm<3>(tmp);
4032       n1/=INTERP_KERNEL::norm<3>(tmp1);
4033       if(n1>eps)
4034         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4035     }
4036   const double *coo=getCoords()->getConstPointer();
4037   for(int i=0;i<getNumberOfNodes();i++)
4038     {
4039       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4040       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4041       res[i]=std::accumulate(tmp,tmp+3,0.);
4042     }
4043 }
4044
4045 /*!
4046  * 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. 
4047  * \a this is expected to be a mesh so that its space dimension is equal to its
4048  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4049  * 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).
4050  *
4051  * 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
4052  * 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).
4053  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4054  *
4055  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4056  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4057  *
4058  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4059  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4060  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4061  * \return the positive value of the distance.
4062  * \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
4063  * dimension - 1.
4064  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4065  */
4066 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4067 {
4068   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4069   if(meshDim!=spaceDim-1)
4070     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4071   if(meshDim!=2 && meshDim!=1)
4072     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4073   checkFullyDefined();
4074   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4075     { 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()); }
4076   DataArrayInt *ret1=0;
4077   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4078   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4079   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4080   cellId=*ret1Safe->begin();
4081   return *ret0->begin();
4082 }
4083
4084 /*!
4085  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4086  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4087  * 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
4088  * 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).
4089  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4090  * 
4091  * \a this is expected to be a mesh so that its space dimension is equal to its
4092  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4093  * 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).
4094  *
4095  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4096  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4097  *
4098  * \param [in] pts the list of points in which each tuple represents a point
4099  * \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.
4100  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4101  * \throw if number of components of \a pts is not equal to the space dimension.
4102  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4103  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4104  */
4105 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4106 {
4107   if(!pts)
4108     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4109   pts->checkAllocated();
4110   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4111   if(meshDim!=spaceDim-1)
4112     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4113   if(meshDim!=2 && meshDim!=1)
4114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4115   if(pts->getNumberOfComponents()!=spaceDim)
4116     {
4117       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4118       throw INTERP_KERNEL::Exception(oss.str().c_str());
4119     }
4120   checkFullyDefined();
4121   int nbCells=getNumberOfCells();
4122   if(nbCells==0)
4123     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4124   int nbOfPts=pts->getNumberOfTuples();
4125   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4126   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4127   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4128   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4129   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4130   const double *bbox(bboxArr->begin());
4131   switch(spaceDim)
4132   {
4133     case 3:
4134       {
4135         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4136         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4137           {
4138             double x=std::numeric_limits<double>::max();
4139             std::vector<int> elems;
4140             myTree.getMinDistanceOfMax(ptsPtr,x);
4141             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4142             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4143           }
4144         break;
4145       }
4146     case 2:
4147       {
4148         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4149         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4150           {
4151             double x=std::numeric_limits<double>::max();
4152             std::vector<int> elems;
4153             myTree.getMinDistanceOfMax(ptsPtr,x);
4154             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4155             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4156           }
4157         break;
4158       }
4159     default:
4160       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4161   }
4162   cellIds=ret1.retn();
4163   return ret0.retn();
4164 }
4165
4166 /// @cond INTERNAL
4167
4168 /*!
4169  * \param [in] pt the start pointer (included) of the coordinates of the point
4170  * \param [in] cellIdsBg the start pointer (included) of cellIds
4171  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4172  * \param [in] nc nodal connectivity
4173  * \param [in] ncI nodal connectivity index
4174  * \param [in,out] ret0 the min distance between \a this and the external input point
4175  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4176  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4177  */
4178 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)
4179 {
4180   cellId=-1;
4181   ret0=std::numeric_limits<double>::max();
4182   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4183     {
4184       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4185       {
4186         case INTERP_KERNEL::NORM_TRI3:
4187           {
4188             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4189             if(tmp<ret0)
4190               { ret0=tmp; cellId=*zeCell; }
4191             break;
4192           }
4193         case INTERP_KERNEL::NORM_QUAD4:
4194         case INTERP_KERNEL::NORM_POLYGON:
4195           {
4196             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4197             if(tmp<ret0)
4198               { ret0=tmp; cellId=*zeCell; }
4199             break;
4200           }
4201         default:
4202           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4203       }
4204     }
4205 }
4206
4207 /*!
4208  * \param [in] pt the start pointer (included) of the coordinates of the point
4209  * \param [in] cellIdsBg the start pointer (included) of cellIds
4210  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4211  * \param [in] nc nodal connectivity
4212  * \param [in] ncI nodal connectivity index
4213  * \param [in,out] ret0 the min distance between \a this and the external input point
4214  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4215  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4216  */
4217 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)
4218 {
4219   cellId=-1;
4220   ret0=std::numeric_limits<double>::max();
4221   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4222     {
4223       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4224       {
4225         case INTERP_KERNEL::NORM_SEG2:
4226           {
4227             std::size_t uselessEntry=0;
4228             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4229             tmp=sqrt(tmp);
4230             if(tmp<ret0)
4231               { ret0=tmp; cellId=*zeCell; }
4232             break;
4233           }
4234         default:
4235           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4236       }
4237     }
4238 }
4239 /// @endcond
4240
4241 /*!
4242  * Finds cells in contact with a ball (i.e. a point with precision). 
4243  * 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.
4244  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4245  *
4246  * \warning This method is suitable if the caller intends to evaluate only one
4247  *          point, for more points getCellsContainingPoints() is recommended as it is
4248  *          faster. 
4249  *  \param [in] pos - array of coordinates of the ball central point.
4250  *  \param [in] eps - ball radius.
4251  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4252  *         if there are no such cells.
4253  *  \throw If the coordinates array is not set.
4254  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4255  */
4256 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4257 {
4258   std::vector<int> elts;
4259   getCellsContainingPoint(pos,eps,elts);
4260   if(elts.empty())
4261     return -1;
4262   return elts.front();
4263 }
4264
4265 /*!
4266  * Finds cells in contact with a ball (i.e. a point with precision).
4267  * 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.
4268  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4269  * \warning This method is suitable if the caller intends to evaluate only one
4270  *          point, for more points getCellsContainingPoints() is recommended as it is
4271  *          faster. 
4272  *  \param [in] pos - array of coordinates of the ball central point.
4273  *  \param [in] eps - ball radius.
4274  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4275  *         before inserting ids.
4276  *  \throw If the coordinates array is not set.
4277  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4278  *
4279  *  \if ENABLE_EXAMPLES
4280  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4281  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4282  *  \endif
4283  */
4284 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4285 {
4286   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4287   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4288   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4289 }
4290
4291 /// @cond INTERNAL
4292
4293 namespace ParaMEDMEM
4294 {
4295   template<const int SPACEDIMM>
4296   class DummyClsMCUG
4297   {
4298   public:
4299     static const int MY_SPACEDIM=SPACEDIMM;
4300     static const int MY_MESHDIM=8;
4301     typedef int MyConnType;
4302     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4303     // begin
4304     // useless, but for windows compilation ...
4305     const double* getCoordinatesPtr() const { return 0; }
4306     const int* getConnectivityPtr() const { return 0; }
4307     const int* getConnectivityIndexPtr() const { return 0; }
4308     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4309     // end
4310   };
4311
4312   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4313   {
4314     INTERP_KERNEL::Edge *ret(0);
4315     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]));
4316     m[n0]=bg[0]; m[n1]=bg[1];
4317     switch(typ)
4318     {
4319       case INTERP_KERNEL::NORM_SEG2:
4320         {
4321           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4322           break;
4323         }
4324       case INTERP_KERNEL::NORM_SEG3:
4325         {
4326           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4327           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4328           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4329           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4330           bool colinearity(inters.areColinears());
4331           delete e1; delete e2;
4332           if(colinearity)
4333             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4334           else
4335             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4336           break;
4337         }
4338       default:
4339         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4340     }
4341     return ret;
4342   }
4343
4344   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4345   {
4346     INTERP_KERNEL::Edge *ret=0;
4347     switch(typ)
4348     {
4349       case INTERP_KERNEL::NORM_SEG2:
4350         {
4351           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4352           break;
4353         }
4354       case INTERP_KERNEL::NORM_SEG3:
4355         {
4356           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4357           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4358           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4359           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4360           bool colinearity=inters.areColinears();
4361           delete e1; delete e2;
4362           if(colinearity)
4363             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4364           else
4365             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4366           mapp2[bg[2]].second=false;
4367           break;
4368         }
4369       default:
4370         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4371     }
4372     return ret;
4373   }
4374
4375   /*!
4376    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4377    * the global mesh 'mDesc'.
4378    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4379    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4380    */
4381   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4382                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4383   {
4384     mapp.clear();
4385     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.
4386     const double *coo=mDesc->getCoords()->getConstPointer();
4387     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4388     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4389     std::set<int> s;
4390     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4391       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4392     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4393       {
4394         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4395         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4396       }
4397     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4398     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4399       {
4400         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4401         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4402       }
4403     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4404       {
4405         if((*it2).second.second)
4406           mapp[(*it2).second.first]=(*it2).first;
4407         ((*it2).second.first)->decrRef();
4408       }
4409     return ret;
4410   }
4411
4412   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4413   {
4414     if(nodeId>=offset2)
4415       {
4416         int locId=nodeId-offset2;
4417         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4418       }
4419     if(nodeId>=offset1)
4420       {
4421         int locId=nodeId-offset1;
4422         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4423       }
4424     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4425   }
4426
4427   /**
4428    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4429    */
4430   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4431                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4432                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4433   {
4434     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4435       {
4436         int eltId1=abs(*desc1)-1;
4437         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4438           {
4439             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4440             if(it==mappRev.end())
4441               {
4442                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4443                 mapp[node]=*it1;
4444                 mappRev[*it1]=node;
4445               }
4446           }
4447       }
4448   }
4449 }
4450
4451 /// @endcond
4452
4453 template<int SPACEDIM>
4454 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4455                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4456 {
4457   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4458   int *eltsIndexPtr(eltsIndex->getPointer());
4459   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4460   const double *bbox(bboxArr->begin());
4461   int nbOfCells=getNumberOfCells();
4462   const int *conn=_nodal_connec->getConstPointer();
4463   const int *connI=_nodal_connec_index->getConstPointer();
4464   double bb[2*SPACEDIM];
4465   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4466   for(int i=0;i<nbOfPoints;i++)
4467     {
4468       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4469       for(int j=0;j<SPACEDIM;j++)
4470         {
4471           bb[2*j]=pos[SPACEDIM*i+j];
4472           bb[2*j+1]=pos[SPACEDIM*i+j];
4473         }
4474       std::vector<int> candidates;
4475       myTree.getIntersectingElems(bb,candidates);
4476       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4477         {
4478           int sz(connI[(*iter)+1]-connI[*iter]-1);
4479           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4480           bool status(false);
4481           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4482             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4483           else
4484             {
4485               if(SPACEDIM!=2)
4486                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4487               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4488               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4489               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4490               INTERP_KERNEL::QuadraticPolygon *pol(0);
4491               for(int j=0;j<sz;j++)
4492                 {
4493                   int nodeId(conn[connI[*iter]+1+j]);
4494                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4495                 }
4496               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4497                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4498               else
4499                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4500               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4501               double a(0.),b(0.),c(0.);
4502               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4503               status=pol->isInOrOut2(n);
4504               delete pol; n->decrRef();
4505             }
4506           if(status)
4507             {
4508               eltsIndexPtr[i+1]++;
4509               elts->pushBackSilent(*iter);
4510             }
4511         }
4512     }
4513 }
4514 /*!
4515  * Finds cells in contact with several balls (i.e. points with precision).
4516  * This method is an extension of getCellContainingPoint() and
4517  * getCellsContainingPoint() for the case of multiple points.
4518  * 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.
4519  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4520  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4521  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4522  *         this->getSpaceDimension() * \a nbOfPoints 
4523  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4524  *  \param [in] eps - radius of balls (i.e. the precision).
4525  *  \param [out] elts - vector returning ids of found cells.
4526  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4527  *         dividing cell ids in \a elts into groups each referring to one
4528  *         point. Its every element (except the last one) is an index pointing to the
4529  *         first id of a group of cells. For example cells in contact with the *i*-th
4530  *         point are described by following range of indices:
4531  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4532  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4533  *         Number of cells in contact with the *i*-th point is
4534  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4535  *  \throw If the coordinates array is not set.
4536  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4537  *
4538  *  \if ENABLE_EXAMPLES
4539  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4540  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4541  *  \endif
4542  */
4543 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4544                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4545 {
4546   int spaceDim=getSpaceDimension();
4547   int mDim=getMeshDimension();
4548   if(spaceDim==3)
4549     {
4550       if(mDim==3)
4551         {
4552           const double *coords=_coords->getConstPointer();
4553           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4554         }
4555       /*else if(mDim==2)
4556         {
4557
4558         }*/
4559       else
4560         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4561     }
4562   else if(spaceDim==2)
4563     {
4564       if(mDim==2)
4565         {
4566           const double *coords=_coords->getConstPointer();
4567           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4568         }
4569       else
4570         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4571     }
4572   else if(spaceDim==1)
4573     {
4574       if(mDim==1)
4575         {
4576           const double *coords=_coords->getConstPointer();
4577           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4578         }
4579       else
4580         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4581     }
4582   else
4583     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4584 }
4585
4586 /*!
4587  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4588  * least two its edges intersect each other anywhere except their extremities. An
4589  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4590  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4591  *         cleared before filling in.
4592  *  \param [in] eps - precision.
4593  *  \throw If \a this->getMeshDimension() != 2.
4594  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4595  */
4596 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4597 {
4598   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4599   if(getMeshDimension()!=2)
4600     throw INTERP_KERNEL::Exception(msg);
4601   int spaceDim=getSpaceDimension();
4602   if(spaceDim!=2 && spaceDim!=3)
4603     throw INTERP_KERNEL::Exception(msg);
4604   const int *conn=_nodal_connec->getConstPointer();
4605   const int *connI=_nodal_connec_index->getConstPointer();
4606   int nbOfCells=getNumberOfCells();
4607   std::vector<double> cell2DinS2;
4608   for(int i=0;i<nbOfCells;i++)
4609     {
4610       int offset=connI[i];
4611       int nbOfNodesForCell=connI[i+1]-offset-1;
4612       if(nbOfNodesForCell<=3)
4613         continue;
4614       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4615       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4616       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4617         cells.push_back(i);
4618       cell2DinS2.clear();
4619     }
4620 }
4621
4622 /*!
4623  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4624  *
4625  * 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.
4626  * 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.
4627  * 
4628  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4629  * This convex envelop is computed using Jarvis march algorithm.
4630  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4631  * 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)
4632  * 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.
4633  *
4634  * \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.
4635  * \sa MEDCouplingUMesh::colinearize2D
4636  */
4637 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4638 {
4639   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4640     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4641   checkFullyDefined();
4642   const double *coords=getCoords()->getConstPointer();
4643   int nbOfCells=getNumberOfCells();
4644   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4645   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4646   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4647   int *workIndexOut=nodalConnecIndexOut->getPointer();
4648   *workIndexOut=0;
4649   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4650   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4651   std::set<INTERP_KERNEL::NormalizedCellType> types;
4652   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4653   isChanged->alloc(0,1);
4654   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4655     {
4656       int pos=nodalConnecOut->getNumberOfTuples();
4657       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4658         isChanged->pushBackSilent(i);
4659       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4660       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4661     }
4662   if(isChanged->empty())
4663     return 0;
4664   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4665   _types=types;
4666   return isChanged.retn();
4667 }
4668
4669 /*!
4670  * This method is \b NOT const because it can modify \a this.
4671  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4672  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4673  * \param policy specifies the type of extrusion chosen:
4674  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4675  *   will be repeated to build each level
4676  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4677  *   the 3 preceding points of the 1D mesh. The center of the arc is the center of rotation for each level, the rotation is done
4678  *   along an axis normal to the plane containing the arc, and finally the angle of rotation is defined by the first two points on the
4679  *   arc.
4680  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4681  */
4682 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4683 {
4684   checkFullyDefined();
4685   mesh1D->checkFullyDefined();
4686   if(!mesh1D->isContiguous1D())
4687     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4688   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4689     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4690   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4691     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4692   if(mesh1D->getMeshDimension()!=1)
4693     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4694   bool isQuad=false;
4695   if(isPresenceOfQuadratic())
4696     {
4697       if(mesh1D->isFullyQuadratic())
4698         isQuad=true;
4699       else
4700         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4701     }
4702   int oldNbOfNodes(getNumberOfNodes());
4703   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4704   switch(policy)
4705   {
4706     case 0:
4707       {
4708         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4709         break;
4710       }
4711     case 1:
4712       {
4713         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4714         break;
4715       }
4716     default:
4717       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4718   }
4719   setCoords(newCoords);
4720   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4721   updateTime();
4722   return ret.retn();
4723 }
4724
4725 /*!
4726  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4727  * If it is not the case an exception will be thrown.
4728  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4729  * intersection of plane defined by ('origin','vec').
4730  * This method has one in/out parameter : 'cut3DCurve'.
4731  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4732  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4733  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4734  * This method will throw an exception if \a this contains a non linear segment.
4735  */
4736 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4737 {
4738   checkFullyDefined();
4739   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4740     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4741   int ncells=getNumberOfCells();
4742   int nnodes=getNumberOfNodes();
4743   double vec2[3],vec3[3],vec4[3];
4744   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4745   if(normm<1e-6)
4746     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4747   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4748   const int *conn=_nodal_connec->getConstPointer();
4749   const int *connI=_nodal_connec_index->getConstPointer();
4750   const double *coo=_coords->getConstPointer();
4751   std::vector<double> addCoo;
4752   for(int i=0;i<ncells;i++)
4753     {
4754       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4755         {
4756           if(cut3DCurve[i]==-2)
4757             {
4758               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4759               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];
4760               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4761               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4762               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4763                 {
4764                   const double *st2=coo+3*st;
4765                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4766                   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]));
4767                   if(pos>eps && pos<1-eps)
4768                     {
4769                       int nNode=((int)addCoo.size())/3;
4770                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4771                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4772                       cut3DCurve[i]=nnodes+nNode;
4773                     }
4774                 }
4775             }
4776         }
4777       else
4778         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4779     }
4780   if(!addCoo.empty())
4781     {
4782       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4783       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4784       coo2->alloc(newNbOfNodes,3);
4785       double *tmp=coo2->getPointer();
4786       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4787       std::copy(addCoo.begin(),addCoo.end(),tmp);
4788       DataArrayDouble::SetArrayIn(coo2,_coords);
4789     }
4790 }
4791
4792 /*!
4793  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4794  * \param mesh1D is the input 1D mesh used for translation computation.
4795  * \return newCoords new coords filled by this method. 
4796  */
4797 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4798 {
4799   int oldNbOfNodes=getNumberOfNodes();
4800   int nbOf1DCells=mesh1D->getNumberOfCells();
4801   int spaceDim=getSpaceDimension();
4802   DataArrayDouble *ret=DataArrayDouble::New();
4803   std::vector<bool> isQuads;
4804   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4805   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4806   double *retPtr=ret->getPointer();
4807   const double *coords=getCoords()->getConstPointer();
4808   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4809   std::vector<int> v;
4810   std::vector<double> c;
4811   double vec[3];
4812   v.reserve(3);
4813   c.reserve(6);
4814   for(int i=0;i<nbOf1DCells;i++)
4815     {
4816       v.resize(0);
4817       mesh1D->getNodeIdsOfCell(i,v);
4818       c.resize(0);
4819       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4820       mesh1D->getCoordinatesOfNode(v[0],c);
4821       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4822       for(int j=0;j<oldNbOfNodes;j++)
4823         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4824       if(isQuad)
4825         {
4826           c.resize(0);
4827           mesh1D->getCoordinatesOfNode(v[1],c);
4828           mesh1D->getCoordinatesOfNode(v[0],c);
4829           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4830           for(int j=0;j<oldNbOfNodes;j++)
4831             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4832         }
4833     }
4834   ret->copyStringInfoFrom(*getCoords());
4835   return ret;
4836 }
4837
4838 /*!
4839  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4840  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4841  * \return newCoords new coords filled by this method. 
4842  */
4843 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4844 {
4845   if(mesh1D->getSpaceDimension()==2)
4846     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4847   if(mesh1D->getSpaceDimension()==3)
4848     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4849   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4850 }
4851
4852 /*!
4853  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4854  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4855  * \return newCoords new coords filled by this method. 
4856  */
4857 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4858 {
4859   if(isQuad)
4860     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4861   int oldNbOfNodes=getNumberOfNodes();
4862   int nbOf1DCells=mesh1D->getNumberOfCells();
4863   if(nbOf1DCells<2)
4864     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4865   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4866   int nbOfLevsInVec=nbOf1DCells+1;
4867   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4868   double *retPtr=ret->getPointer();
4869   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4870   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4871   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4872   tmp->setCoords(tmp2);
4873   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4874   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4875   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4876   for(int i=1;i<nbOfLevsInVec;i++)
4877     {
4878       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4879       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4880       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4881       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4882       tmp->translate(vec);
4883       double tmp3[2],radius,alpha,alpha0;
4884       const double *p0=i+1<nbOfLevsInVec?begin:third;
4885       const double *p1=i+1<nbOfLevsInVec?end:begin;
4886       const double *p2=i+1<nbOfLevsInVec?third:end;
4887       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4888       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]);
4889       double angle=acos(cosangle/(radius*radius));
4890       tmp->rotate(end,0,angle);
4891       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4892     }
4893   return ret.retn();
4894 }
4895
4896 /*!
4897  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4898  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4899  * \return newCoords new coords filled by this method. 
4900  */
4901 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4902 {
4903   if(isQuad)
4904     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4905   int oldNbOfNodes=getNumberOfNodes();
4906   int nbOf1DCells=mesh1D->getNumberOfCells();
4907   if(nbOf1DCells<2)
4908     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4909   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4910   int nbOfLevsInVec=nbOf1DCells+1;
4911   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4912   double *retPtr=ret->getPointer();
4913   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4914   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4915   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4916   tmp->setCoords(tmp2);
4917   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4918   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4919   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4920   for(int i=1;i<nbOfLevsInVec;i++)
4921     {
4922       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4923       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4924       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4925       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4926       tmp->translate(vec);
4927       double tmp3[2],radius,alpha,alpha0;
4928       const double *p0=i+1<nbOfLevsInVec?begin:third;
4929       const double *p1=i+1<nbOfLevsInVec?end:begin;
4930       const double *p2=i+1<nbOfLevsInVec?third:end;
4931       double vecPlane[3]={
4932         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4933         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4934         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4935       };
4936       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4937       if(norm>1.e-7)
4938         {
4939           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4940           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4941           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4942           double s2=norm2;
4943           double c2=cos(asin(s2));
4944           double m[3][3]={
4945             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4946             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4947             {-vec2[1]*s2, vec2[0]*s2, c2}
4948           };
4949           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]};
4950           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]};
4951           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]};
4952           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4953           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]);
4954           double angle=acos(cosangle/(radius*radius));
4955           tmp->rotate(end,vecPlane,angle);
4956         }
4957       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4958     }
4959   return ret.retn();
4960 }
4961
4962 /*!
4963  * This method is private because not easy to use for end user. This method is const contrary to
4964  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4965  * the coords sorted slice by slice.
4966  * \param isQuad specifies presence of quadratic cells.
4967  */
4968 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4969 {
4970   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4971   int nbOf2DCells(getNumberOfCells());
4972   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4973   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4974   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4976   newConnI->alloc(nbOf3DCells+1,1);
4977   int *newConnIPtr(newConnI->getPointer());
4978   *newConnIPtr++=0;
4979   std::vector<int> newc;
4980   for(int j=0;j<nbOf2DCells;j++)
4981     {
4982       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4983       *newConnIPtr++=(int)newc.size();
4984     }
4985   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4986   int *newConnPtr(newConn->getPointer());
4987   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4988   newConnIPtr=newConnI->getPointer();
4989   for(int iz=0;iz<nbOf1DCells;iz++)
4990     {
4991       if(iz!=0)
4992         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4993       const int *posOfTypeOfCell(newConnIPtr);
4994       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4995         {
4996           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4997           if(icell!=*posOfTypeOfCell)
4998             {
4999               if(*iter!=-1)
5000                 *newConnPtr=(*iter)+iz*deltaPerLev;
5001               else
5002                 *newConnPtr=-1;
5003             }
5004           else
5005             {
5006               *newConnPtr=*iter;
5007               posOfTypeOfCell++;
5008             }
5009         }
5010     }
5011   ret->setConnectivity(newConn,newConnI,true);
5012   ret->setCoords(getCoords());
5013   return ret;
5014 }
5015
5016 /*!
5017  * Checks if \a this mesh is constituted by only quadratic cells.
5018  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
5019  *  \throw If the coordinates array is not set.
5020  *  \throw If the nodal connectivity of cells is not defined.
5021  */
5022 bool MEDCouplingUMesh::isFullyQuadratic() const
5023 {
5024   checkFullyDefined();
5025   bool ret=true;
5026   int nbOfCells=getNumberOfCells();
5027   for(int i=0;i<nbOfCells && ret;i++)
5028     {
5029       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5030       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5031       ret=cm.isQuadratic();
5032     }
5033   return ret;
5034 }
5035
5036 /*!
5037  * Checks if \a this mesh includes any quadratic cell.
5038  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5039  *  \throw If the coordinates array is not set.
5040  *  \throw If the nodal connectivity of cells is not defined.
5041  */
5042 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5043 {
5044   checkFullyDefined();
5045   bool ret=false;
5046   int nbOfCells=getNumberOfCells();
5047   for(int i=0;i<nbOfCells && !ret;i++)
5048     {
5049       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5050       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5051       ret=cm.isQuadratic();
5052     }
5053   return ret;
5054 }
5055
5056 /*!
5057  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5058  * this mesh, it remains unchanged.
5059  *  \throw If the coordinates array is not set.
5060  *  \throw If the nodal connectivity of cells is not defined.
5061  */
5062 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5063 {
5064   checkFullyDefined();
5065   int nbOfCells=getNumberOfCells();
5066   int delta=0;
5067   const int *iciptr=_nodal_connec_index->getConstPointer();
5068   for(int i=0;i<nbOfCells;i++)
5069     {
5070       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5071       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5072       if(cm.isQuadratic())
5073         {
5074           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5075           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5076           if(!cml.isDynamic())
5077             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5078           else
5079             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5080         }
5081     }
5082   if(delta==0)
5083     return ;
5084   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5085   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5086   const int *icptr=_nodal_connec->getConstPointer();
5087   newConn->alloc(getMeshLength()-delta,1);
5088   newConnI->alloc(nbOfCells+1,1);
5089   int *ocptr=newConn->getPointer();
5090   int *ociptr=newConnI->getPointer();
5091   *ociptr=0;
5092   _types.clear();
5093   for(int i=0;i<nbOfCells;i++,ociptr++)
5094     {
5095       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5096       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5097       if(!cm.isQuadratic())
5098         {
5099           _types.insert(type);
5100           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5101           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5102         }
5103       else
5104         {
5105           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5106           _types.insert(typel);
5107           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5108           int newNbOfNodes=cml.getNumberOfNodes();
5109           if(cml.isDynamic())
5110             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5111           *ocptr++=(int)typel;
5112           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5113           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5114         }
5115     }
5116   setConnectivity(newConn,newConnI,false);
5117 }
5118
5119 /*!
5120  * This method converts all linear cell in \a this to quadratic one.
5121  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5122  * 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)
5123  * 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.
5124  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5125  * end of the existing coordinates.
5126  * 
5127  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5128  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5129  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5130  * 
5131  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5132  *
5133  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5134  */
5135 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5136 {
5137   DataArrayInt *conn=0,*connI=0;
5138   DataArrayDouble *coords=0;
5139   std::set<INTERP_KERNEL::NormalizedCellType> types;
5140   checkFullyDefined();
5141   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5142   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5143   int meshDim=getMeshDimension();
5144   switch(conversionType)
5145   {
5146     case 0:
5147       switch(meshDim)
5148       {
5149         case 1:
5150           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5151           connSafe=conn; connISafe=connI; coordsSafe=coords;
5152           break;
5153         case 2:
5154           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5155           connSafe=conn; connISafe=connI; coordsSafe=coords;
5156           break;
5157         case 3:
5158           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5159           connSafe=conn; connISafe=connI; coordsSafe=coords;
5160           break;
5161         default:
5162           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5163       }
5164       break;
5165         case 1:
5166           {
5167             switch(meshDim)
5168             {
5169               case 1:
5170                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5171                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5172                 break;
5173               case 2:
5174                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5175                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5176                 break;
5177               case 3:
5178                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5179                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5180                 break;
5181               default:
5182                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5183             }
5184             break;
5185           }
5186         default:
5187           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5188   }
5189   setConnectivity(connSafe,connISafe,false);
5190   _types=types;
5191   setCoords(coordsSafe);
5192   return ret.retn();
5193 }
5194
5195 #if 0
5196 /*!
5197  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5198  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5199  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5200  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5201  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5202  * This method can be seen as the opposite method of colinearize2D.
5203  * 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
5204  * to avoid to modify the numbering of existing nodes.
5205  *
5206  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5207  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5208  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5209  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5210  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5211  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5212  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5213  *
5214  * \sa buildDescendingConnectivity2
5215  */
5216 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5217                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5218 {
5219   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5220     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5221   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5222   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5223     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5224   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5225     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5226   //DataArrayInt *out0(0),*outi0(0);
5227   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5228   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5229   //out0s=out0s->buildUnique(); out0s->sort(true);
5230 }
5231 #endif
5232
5233 /*!
5234  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5235  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5236  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5237  */
5238 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5239 {
5240   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5244   int nbOfCells=getNumberOfCells();
5245   int nbOfNodes=getNumberOfNodes();
5246   const int *cPtr=_nodal_connec->getConstPointer();
5247   const int *icPtr=_nodal_connec_index->getConstPointer();
5248   int lastVal=0,offset=nbOfNodes;
5249   for(int i=0;i<nbOfCells;i++,icPtr++)
5250     {
5251       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5252       if(type==INTERP_KERNEL::NORM_SEG2)
5253         {
5254           types.insert(INTERP_KERNEL::NORM_SEG3);
5255           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5256           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5257           newConn->pushBackSilent(offset++);
5258           lastVal+=4;
5259           newConnI->pushBackSilent(lastVal);
5260           ret->pushBackSilent(i);
5261         }
5262       else
5263         {
5264           types.insert(type);
5265           lastVal+=(icPtr[1]-icPtr[0]);
5266           newConnI->pushBackSilent(lastVal);
5267           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5268         }
5269     }
5270   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5271   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5272   return ret.retn();
5273 }
5274
5275 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
5276 {
5277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5280   //
5281   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5282   DataArrayInt *conn1D=0,*conn1DI=0;
5283   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5284   DataArrayDouble *coordsTmp=0;
5285   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5286   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5287   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5288   const int *c1DPtr=conn1D->begin();
5289   const int *c1DIPtr=conn1DI->begin();
5290   int nbOfCells=getNumberOfCells();
5291   const int *cPtr=_nodal_connec->getConstPointer();
5292   const int *icPtr=_nodal_connec_index->getConstPointer();
5293   int lastVal=0;
5294   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5295     {
5296       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5297       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5298       if(!cm.isQuadratic())
5299         {
5300           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5301           types.insert(typ2); newConn->pushBackSilent(typ2);
5302           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5303           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5304             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5305           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5306           newConnI->pushBackSilent(lastVal);
5307           ret->pushBackSilent(i);
5308         }
5309       else
5310         {
5311           types.insert(typ);
5312           lastVal+=(icPtr[1]-icPtr[0]);
5313           newConnI->pushBackSilent(lastVal);
5314           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5315         }
5316     }
5317   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5318   return ret.retn();
5319 }
5320
5321 /*!
5322  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5323  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5324  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5325  */
5326 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5327 {
5328   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5329   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5330   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5331 }
5332
5333 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5334 {
5335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5336   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5337   //
5338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5339   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5340   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5341   //
5342   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5343   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5344   DataArrayInt *conn1D=0,*conn1DI=0;
5345   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5346   DataArrayDouble *coordsTmp=0;
5347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5348   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5349   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5350   const int *c1DPtr=conn1D->begin();
5351   const int *c1DIPtr=conn1DI->begin();
5352   int nbOfCells=getNumberOfCells();
5353   const int *cPtr=_nodal_connec->getConstPointer();
5354   const int *icPtr=_nodal_connec_index->getConstPointer();
5355   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5356   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5357     {
5358       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5359       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5360       if(!cm.isQuadratic())
5361         {
5362           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5363           types.insert(typ2); newConn->pushBackSilent(typ2);
5364           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5365           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5366             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5367           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5368           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5369           newConnI->pushBackSilent(lastVal);
5370           ret->pushBackSilent(i);
5371         }
5372       else
5373         {
5374           types.insert(typ);
5375           lastVal+=(icPtr[1]-icPtr[0]);
5376           newConnI->pushBackSilent(lastVal);
5377           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5378         }
5379     }
5380   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5381   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5382   return ret.retn();
5383 }
5384
5385 /*!
5386  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5387  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5388  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5389  */
5390 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5391 {
5392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5393   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5394   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5395 }
5396
5397 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5398 {
5399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5400   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5401   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5402   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5403   //
5404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5406   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5407   //
5408   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5409   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5410   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5411   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5412   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5413   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5414   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5415   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5416   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5417   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5418   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5419   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5420   int nbOfCells=getNumberOfCells();
5421   const int *cPtr=_nodal_connec->getConstPointer();
5422   const int *icPtr=_nodal_connec_index->getConstPointer();
5423   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5424   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5425     {
5426       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5427       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5428       if(!cm.isQuadratic())
5429         {
5430           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5431           if(typ2==INTERP_KERNEL::NORM_ERROR)
5432             {
5433               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5434               throw INTERP_KERNEL::Exception(oss.str().c_str());
5435             }
5436           types.insert(typ2); newConn->pushBackSilent(typ2);
5437           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5438           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5439             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5440           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5441             {
5442               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5443               int tmpPos=newConn->getNumberOfTuples();
5444               newConn->pushBackSilent(nodeId2);
5445               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5446             }
5447           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5448           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5449           newConnI->pushBackSilent(lastVal);
5450           ret->pushBackSilent(i);
5451         }
5452       else
5453         {
5454           types.insert(typ);
5455           lastVal+=(icPtr[1]-icPtr[0]);
5456           newConnI->pushBackSilent(lastVal);
5457           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5458         }
5459     }
5460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5461   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5462   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5463   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5464   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5465   int *c=newConn->getPointer();
5466   const int *cI(newConnI->begin());
5467   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5468     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5469   offset=coordsTmp2Safe->getNumberOfTuples();
5470   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5471     c[cI[(*elt)+1]-1]+=offset;
5472   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5473   return ret.retn();
5474 }
5475
5476 /*!
5477  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5478  * so that the number of cells remains the same. Quadratic faces are converted to
5479  * polygons. This method works only for 2D meshes in
5480  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5481  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5482  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5483  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5484  *         a polylinized edge constituting the input polygon.
5485  *  \throw If the coordinates array is not set.
5486  *  \throw If the nodal connectivity of cells is not defined.
5487  *  \throw If \a this->getMeshDimension() != 2.
5488  *  \throw If \a this->getSpaceDimension() != 2.
5489  */
5490 void MEDCouplingUMesh::tessellate2D(double eps)
5491 {
5492   checkFullyDefined();
5493   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5494     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5495   double epsa=fabs(eps);
5496   if(epsa<std::numeric_limits<double>::min())
5497     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 !");
5498   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5499   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5500   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5501   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5502   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5503   revDesc1=0; revDescIndx1=0;
5504   mDesc->tessellate2DCurve(eps);
5505   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5506   setCoords(mDesc->getCoords());
5507 }
5508
5509 /*!
5510  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5511  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5512  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5513  *         a sub-divided edge.
5514  *  \throw If the coordinates array is not set.
5515  *  \throw If the nodal connectivity of cells is not defined.
5516  *  \throw If \a this->getMeshDimension() != 1.
5517  *  \throw If \a this->getSpaceDimension() != 2.
5518  */
5519 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5520 {
5521   checkFullyDefined();
5522   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5523     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5524   double epsa=fabs(eps);
5525   if(epsa<std::numeric_limits<double>::min())
5526     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 !");
5527   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5528   int nbCells=getNumberOfCells();
5529   int nbNodes=getNumberOfNodes();
5530   const int *conn=_nodal_connec->getConstPointer();
5531   const int *connI=_nodal_connec_index->getConstPointer();
5532   const double *coords=_coords->getConstPointer();
5533   std::vector<double> addCoo;
5534   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5535   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5536   newConnI->alloc(nbCells+1,1);
5537   int *newConnIPtr=newConnI->getPointer();
5538   *newConnIPtr=0;
5539   int tmp1[3];
5540   INTERP_KERNEL::Node *tmp2[3];
5541   std::set<INTERP_KERNEL::NormalizedCellType> types;
5542   for(int i=0;i<nbCells;i++,newConnIPtr++)
5543     {
5544       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5545       if(cm.isQuadratic())
5546         {//assert(connI[i+1]-connI[i]-1==3)
5547           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5548           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5549           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5550           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5551           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5552           if(eac)
5553             {
5554               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5555               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5556               delete eac;
5557               newConnIPtr[1]=(int)newConn.size();
5558             }
5559           else
5560             {
5561               types.insert(INTERP_KERNEL::NORM_SEG2);
5562               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5563               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5564               newConnIPtr[1]=newConnIPtr[0]+3;
5565             }
5566         }
5567       else
5568         {
5569           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5570           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5571           newConnIPtr[1]=newConnIPtr[0]+3;
5572         }
5573     }
5574   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5575     return ;
5576   _types=types;
5577   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5578   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5579   newConnArr->alloc((int)newConn.size(),1);
5580   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5581   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5582   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5583   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5584   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5585   std::copy(addCoo.begin(),addCoo.end(),work);
5586   DataArrayDouble::SetArrayIn(newCoords,_coords);
5587   updateTime();
5588 }
5589
5590 /*!
5591  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5592  * In addition, returns an array mapping new cells to old ones. <br>
5593  * This method typically increases the number of cells in \a this mesh
5594  * but the number of nodes remains \b unchanged.
5595  * That's why the 3D splitting policies
5596  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5597  *  \param [in] policy - specifies a pattern used for splitting.
5598  * The semantic of \a policy is:
5599  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5600  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5601  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5602  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5603  *
5604  *
5605  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5606  *          an id of old cell producing it. The caller is to delete this array using
5607  *         decrRef() as it is no more needed.
5608  *
5609  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5610  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5611  *          and \a this->getMeshDimension() != 3. 
5612  *  \throw If \a policy is not one of the four discussed above.
5613  *  \throw If the nodal connectivity of cells is not defined.
5614  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5615  */
5616 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5617 {
5618   switch(policy)
5619   {
5620     case 0:
5621       return simplexizePol0();
5622     case 1:
5623       return simplexizePol1();
5624     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5625         return simplexizePlanarFace5();
5626     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5627         return simplexizePlanarFace6();
5628     default:
5629       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)");
5630   }
5631 }
5632
5633 /*!
5634  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5635  * - 1D: INTERP_KERNEL::NORM_SEG2
5636  * - 2D: INTERP_KERNEL::NORM_TRI3
5637  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5638  *
5639  * This method is useful for users that need to use P1 field services as
5640  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5641  * All these methods need mesh support containing only simplex cells.
5642  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5643  *  \throw If the coordinates array is not set.
5644  *  \throw If the nodal connectivity of cells is not defined.
5645  *  \throw If \a this->getMeshDimension() < 1.
5646  */
5647 bool MEDCouplingUMesh::areOnlySimplexCells() const
5648 {
5649   checkFullyDefined();
5650   int mdim=getMeshDimension();
5651   if(mdim<1 || mdim>3)
5652     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5653   int nbCells=getNumberOfCells();
5654   const int *conn=_nodal_connec->getConstPointer();
5655   const int *connI=_nodal_connec_index->getConstPointer();
5656   for(int i=0;i<nbCells;i++)
5657     {
5658       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5659       if(!cm.isSimplex())
5660         return false;
5661     }
5662   return true;
5663 }
5664
5665 /*!
5666  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5667  */
5668 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5669 {
5670   checkConnectivityFullyDefined();
5671   if(getMeshDimension()!=2)
5672     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5673   int nbOfCells=getNumberOfCells();
5674   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5675   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5676   ret->alloc(nbOfCells+nbOfCutCells,1);
5677   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5678   int *retPt=ret->getPointer();
5679   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5680   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5681   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5682   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5683   int *pt=newConn->getPointer();
5684   int *ptI=newConnI->getPointer();
5685   ptI[0]=0;
5686   const int *oldc=_nodal_connec->getConstPointer();
5687   const int *ci=_nodal_connec_index->getConstPointer();
5688   for(int i=0;i<nbOfCells;i++,ci++)
5689     {
5690       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5691         {
5692           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5693             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5694           pt=std::copy(tmp,tmp+8,pt);
5695           ptI[1]=ptI[0]+4;
5696           ptI[2]=ptI[0]+8;
5697           *retPt++=i;
5698           *retPt++=i;
5699           ptI+=2;
5700         }
5701       else
5702         {
5703           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5704           ptI[1]=ptI[0]+ci[1]-ci[0];
5705           ptI++;
5706           *retPt++=i;
5707         }
5708     }
5709   _nodal_connec->decrRef();
5710   _nodal_connec=newConn.retn();
5711   _nodal_connec_index->decrRef();
5712   _nodal_connec_index=newConnI.retn();
5713   computeTypes();
5714   updateTime();
5715   return ret.retn();
5716 }
5717
5718 /*!
5719  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5720  */
5721 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5722 {
5723   checkConnectivityFullyDefined();
5724   if(getMeshDimension()!=2)
5725     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5726   int nbOfCells=getNumberOfCells();
5727   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5728   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5729   ret->alloc(nbOfCells+nbOfCutCells,1);
5730   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5731   int *retPt=ret->getPointer();
5732   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5733   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5734   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5735   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5736   int *pt=newConn->getPointer();
5737   int *ptI=newConnI->getPointer();
5738   ptI[0]=0;
5739   const int *oldc=_nodal_connec->getConstPointer();
5740   const int *ci=_nodal_connec_index->getConstPointer();
5741   for(int i=0;i<nbOfCells;i++,ci++)
5742     {
5743       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5744         {
5745           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5746             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5747           pt=std::copy(tmp,tmp+8,pt);
5748           ptI[1]=ptI[0]+4;
5749           ptI[2]=ptI[0]+8;
5750           *retPt++=i;
5751           *retPt++=i;
5752           ptI+=2;
5753         }
5754       else
5755         {
5756           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5757           ptI[1]=ptI[0]+ci[1]-ci[0];
5758           ptI++;
5759           *retPt++=i;
5760         }
5761     }
5762   _nodal_connec->decrRef();
5763   _nodal_connec=newConn.retn();
5764   _nodal_connec_index->decrRef();
5765   _nodal_connec_index=newConnI.retn();
5766   computeTypes();
5767   updateTime();
5768   return ret.retn();
5769 }
5770
5771 /*!
5772  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5773  */
5774 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5775 {
5776   checkConnectivityFullyDefined();
5777   if(getMeshDimension()!=3)
5778     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5779   int nbOfCells=getNumberOfCells();
5780   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5781   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5782   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5783   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5784   int *retPt=ret->getPointer();
5785   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5786   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5787   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5788   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5789   int *pt=newConn->getPointer();
5790   int *ptI=newConnI->getPointer();
5791   ptI[0]=0;
5792   const int *oldc=_nodal_connec->getConstPointer();
5793   const int *ci=_nodal_connec_index->getConstPointer();
5794   for(int i=0;i<nbOfCells;i++,ci++)
5795     {
5796       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5797         {
5798           for(int j=0;j<5;j++,pt+=5,ptI++)
5799             {
5800               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5801               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];
5802               *retPt++=i;
5803               ptI[1]=ptI[0]+5;
5804             }
5805         }
5806       else
5807         {
5808           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5809           ptI[1]=ptI[0]+ci[1]-ci[0];
5810           ptI++;
5811           *retPt++=i;
5812         }
5813     }
5814   _nodal_connec->decrRef();
5815   _nodal_connec=newConn.retn();
5816   _nodal_connec_index->decrRef();
5817   _nodal_connec_index=newConnI.retn();
5818   computeTypes();
5819   updateTime();
5820   return ret.retn();
5821 }
5822
5823 /*!
5824  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5825  */
5826 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5827 {
5828   checkConnectivityFullyDefined();
5829   if(getMeshDimension()!=3)
5830     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5831   int nbOfCells=getNumberOfCells();
5832   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5833   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5834   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5835   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5836   int *retPt=ret->getPointer();
5837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5838   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5839   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5840   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5841   int *pt=newConn->getPointer();
5842   int *ptI=newConnI->getPointer();
5843   ptI[0]=0;
5844   const int *oldc=_nodal_connec->getConstPointer();
5845   const int *ci=_nodal_connec_index->getConstPointer();
5846   for(int i=0;i<nbOfCells;i++,ci++)
5847     {
5848       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5849         {
5850           for(int j=0;j<6;j++,pt+=5,ptI++)
5851             {
5852               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5853               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];
5854               *retPt++=i;
5855               ptI[1]=ptI[0]+5;
5856             }
5857         }
5858       else
5859         {
5860           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5861           ptI[1]=ptI[0]+ci[1]-ci[0];
5862           ptI++;
5863           *retPt++=i;
5864         }
5865     }
5866   _nodal_connec->decrRef();
5867   _nodal_connec=newConn.retn();
5868   _nodal_connec_index->decrRef();
5869   _nodal_connec_index=newConnI.retn();
5870   computeTypes();
5871   updateTime();
5872   return ret.retn();
5873 }
5874
5875 /*!
5876  * 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.
5877  * This method completly ignore coordinates.
5878  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5879  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5880  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5881  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5882  */
5883 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5884 {
5885   checkFullyDefined();
5886   if(getMeshDimension()!=2)
5887     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5888   int nbOfCells=getNumberOfCells();
5889   int *connI=_nodal_connec_index->getPointer();
5890   int newConnLgth=0;
5891   for(int i=0;i<nbOfCells;i++,connI++)
5892     {
5893       int offset=descIndex[i];
5894       int nbOfEdges=descIndex[i+1]-offset;
5895       //
5896       bool ddirect=desc[offset+nbOfEdges-1]>0;
5897       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5898       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5899       for(int j=0;j<nbOfEdges;j++)
5900         {
5901           bool direct=desc[offset+j]>0;
5902           int edgeId=std::abs(desc[offset+j])-1;
5903           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5904             {
5905               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5906               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5907               int ref2=direct?id1:id2;
5908               if(ref==ref2)
5909                 {
5910                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5911                   newConnLgth+=nbOfSubNodes-1;
5912                   ref=direct?id2:id1;
5913                 }
5914               else
5915                 {
5916                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5917                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5918                 }
5919             }
5920           else
5921             {
5922               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5923             }
5924         }
5925       newConnLgth++;//+1 is for cell type
5926       connI[1]=newConnLgth;
5927     }
5928   //
5929   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5930   newConn->alloc(newConnLgth,1);
5931   int *work=newConn->getPointer();
5932   for(int i=0;i<nbOfCells;i++)
5933     {
5934       *work++=INTERP_KERNEL::NORM_POLYGON;
5935       int offset=descIndex[i];
5936       int nbOfEdges=descIndex[i+1]-offset;
5937       for(int j=0;j<nbOfEdges;j++)
5938         {
5939           bool direct=desc[offset+j]>0;
5940           int edgeId=std::abs(desc[offset+j])-1;
5941           if(direct)
5942             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5943           else
5944             {
5945               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5946               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5947               work=std::copy(it,it+nbOfSubNodes-1,work);
5948             }
5949         }
5950     }
5951   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5952   _types.clear();
5953   if(nbOfCells>0)
5954     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5955 }
5956
5957 /*!
5958  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5959  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5960  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5961  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5962  * so it can be useful to call mergeNodes() before calling this method.
5963  *  \throw If \a this->getMeshDimension() <= 1.
5964  *  \throw If the coordinates array is not set.
5965  *  \throw If the nodal connectivity of cells is not defined.
5966  */
5967 void MEDCouplingUMesh::convertDegeneratedCells()
5968 {
5969   checkFullyDefined();
5970   if(getMeshDimension()<=1)
5971     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5972   int nbOfCells=getNumberOfCells();
5973   if(nbOfCells<1)
5974     return ;
5975   int initMeshLgth=getMeshLength();
5976   int *conn=_nodal_connec->getPointer();
5977   int *index=_nodal_connec_index->getPointer();
5978   int posOfCurCell=0;
5979   int newPos=0;
5980   int lgthOfCurCell;
5981   for(int i=0;i<nbOfCells;i++)
5982     {
5983       lgthOfCurCell=index[i+1]-posOfCurCell;
5984       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5985       int newLgth;
5986       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5987                                                                                                      conn+newPos+1,newLgth);
5988       conn[newPos]=newType;
5989       newPos+=newLgth+1;
5990       posOfCurCell=index[i+1];
5991       index[i+1]=newPos;
5992     }
5993   if(newPos!=initMeshLgth)
5994     _nodal_connec->reAlloc(newPos);
5995   computeTypes();
5996 }
5997
5998 /*!
5999  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
6000  * A cell is considered to be oriented correctly if an angle between its
6001  * normal vector and a given vector is less than \c PI / \c 2.
6002  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6003  *         cells. 
6004  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6005  *         checked.
6006  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6007  *         is not cleared before filling in.
6008  *  \throw If \a this->getMeshDimension() != 2.
6009  *  \throw If \a this->getSpaceDimension() != 3.
6010  *
6011  *  \if ENABLE_EXAMPLES
6012  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6013  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6014  *  \endif
6015  */
6016 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6017 {
6018   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6019     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6020   int nbOfCells=getNumberOfCells();
6021   const int *conn=_nodal_connec->getConstPointer();
6022   const int *connI=_nodal_connec_index->getConstPointer();
6023   const double *coordsPtr=_coords->getConstPointer();
6024   for(int i=0;i<nbOfCells;i++)
6025     {
6026       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6027       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6028         {
6029           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6030           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6031             cells.push_back(i);
6032         }
6033     }
6034 }
6035
6036 /*!
6037  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6038  * considered to be oriented correctly if an angle between its normal vector and a
6039  * given vector is less than \c PI / \c 2. 
6040  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6041  *         cells. 
6042  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6043  *         checked.
6044  *  \throw If \a this->getMeshDimension() != 2.
6045  *  \throw If \a this->getSpaceDimension() != 3.
6046  *
6047  *  \if ENABLE_EXAMPLES
6048  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6049  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6050  *  \endif
6051  *
6052  *  \sa changeOrientationOfCells
6053  */
6054 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6055 {
6056   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6057     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6058   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6059   const int *connI(_nodal_connec_index->getConstPointer());
6060   const double *coordsPtr(_coords->getConstPointer());
6061   bool isModified(false);
6062   for(int i=0;i<nbOfCells;i++)
6063     {
6064       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6065       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6066         {
6067           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6068           bool isQuadratic(cm.isQuadratic());
6069           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6070             {
6071               isModified=true;
6072               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6073             }
6074         }
6075     }
6076   if(isModified)
6077     _nodal_connec->declareAsNew();
6078   updateTime();
6079 }
6080
6081 /*!
6082  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6083  *
6084  * \sa orientCorrectly2DCells
6085  */
6086 void MEDCouplingUMesh::changeOrientationOfCells()
6087 {
6088   int mdim(getMeshDimension());
6089   if(mdim!=2 && mdim!=1)
6090     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6091   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6092   const int *connI(_nodal_connec_index->getConstPointer());
6093   if(mdim==2)
6094     {//2D
6095       for(int i=0;i<nbOfCells;i++)
6096         {
6097           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6098           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6099           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6100         }
6101     }
6102   else
6103     {//1D
6104       for(int i=0;i<nbOfCells;i++)
6105         {
6106           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6107           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6108           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6109         }
6110     }
6111 }
6112
6113 /*!
6114  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6115  * oriented facets. The normal vector of the facet should point out of the cell.
6116  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6117  *         is not cleared before filling in.
6118  *  \throw If \a this->getMeshDimension() != 3.
6119  *  \throw If \a this->getSpaceDimension() != 3.
6120  *  \throw If the coordinates array is not set.
6121  *  \throw If the nodal connectivity of cells is not defined.
6122  *
6123  *  \if ENABLE_EXAMPLES
6124  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6125  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6126  *  \endif
6127  */
6128 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6129 {
6130   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6131     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6132   int nbOfCells=getNumberOfCells();
6133   const int *conn=_nodal_connec->getConstPointer();
6134   const int *connI=_nodal_connec_index->getConstPointer();
6135   const double *coordsPtr=_coords->getConstPointer();
6136   for(int i=0;i<nbOfCells;i++)
6137     {
6138       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6139       if(type==INTERP_KERNEL::NORM_POLYHED)
6140         {
6141           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6142             cells.push_back(i);
6143         }
6144     }
6145 }
6146
6147 /*!
6148  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6149  * out of the cell. 
6150  *  \throw If \a this->getMeshDimension() != 3.
6151  *  \throw If \a this->getSpaceDimension() != 3.
6152  *  \throw If the coordinates array is not set.
6153  *  \throw If the nodal connectivity of cells is not defined.
6154  *  \throw If the reparation fails.
6155  *
6156  *  \if ENABLE_EXAMPLES
6157  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6158  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6159  *  \endif
6160  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6161  */
6162 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6163 {
6164   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6165     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6166   int nbOfCells=getNumberOfCells();
6167   int *conn=_nodal_connec->getPointer();
6168   const int *connI=_nodal_connec_index->getConstPointer();
6169   const double *coordsPtr=_coords->getConstPointer();
6170   for(int i=0;i<nbOfCells;i++)
6171     {
6172       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6173       if(type==INTERP_KERNEL::NORM_POLYHED)
6174         {
6175           try
6176           {
6177               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6178                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6179           }
6180           catch(INTERP_KERNEL::Exception& e)
6181           {
6182               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6183               throw INTERP_KERNEL::Exception(oss.str().c_str());
6184           }
6185         }
6186     }
6187   updateTime();
6188 }
6189
6190 /*!
6191  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6192  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6193  * according to which the first facet of the cell should be oriented to have the normal vector
6194  * pointing out of cell.
6195  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6196  *         cells. The caller is to delete this array using decrRef() as it is no more
6197  *         needed. 
6198  *  \throw If \a this->getMeshDimension() != 3.
6199  *  \throw If \a this->getSpaceDimension() != 3.
6200  *  \throw If the coordinates array is not set.
6201  *  \throw If the nodal connectivity of cells is not defined.
6202  *
6203  *  \if ENABLE_EXAMPLES
6204  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6205  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6206  *  \endif
6207  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6208  */
6209 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6210 {
6211   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6212   if(getMeshDimension()!=3)
6213     throw INTERP_KERNEL::Exception(msg);
6214   int spaceDim=getSpaceDimension();
6215   if(spaceDim!=3)
6216     throw INTERP_KERNEL::Exception(msg);
6217   //
6218   int nbOfCells=getNumberOfCells();
6219   int *conn=_nodal_connec->getPointer();
6220   const int *connI=_nodal_connec_index->getConstPointer();
6221   const double *coo=getCoords()->getConstPointer();
6222   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6223   for(int i=0;i<nbOfCells;i++)
6224     {
6225       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6226       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6227         {
6228           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6229             {
6230               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6231               cells->pushBackSilent(i);
6232             }
6233         }
6234     }
6235   return cells.retn();
6236 }
6237
6238 /*!
6239  * This method is a faster method to correct orientation of all 3D cells in \a this.
6240  * 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.
6241  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6242  * 
6243  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6244  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6245  */
6246 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6247 {
6248   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6249     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6250   int nbOfCells=getNumberOfCells();
6251   int *conn=_nodal_connec->getPointer();
6252   const int *connI=_nodal_connec_index->getConstPointer();
6253   const double *coordsPtr=_coords->getConstPointer();
6254   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6255   for(int i=0;i<nbOfCells;i++)
6256     {
6257       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6258       switch(type)
6259       {
6260         case INTERP_KERNEL::NORM_TETRA4:
6261           {
6262             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6263               {
6264                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6265                 ret->pushBackSilent(i);
6266               }
6267             break;
6268           }
6269         case INTERP_KERNEL::NORM_PYRA5:
6270           {
6271             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6272               {
6273                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6274                 ret->pushBackSilent(i);
6275               }
6276             break;
6277           }
6278         case INTERP_KERNEL::NORM_PENTA6:
6279         case INTERP_KERNEL::NORM_HEXA8:
6280         case INTERP_KERNEL::NORM_HEXGP12:
6281           {
6282             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6283               {
6284                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6285                 ret->pushBackSilent(i);
6286               }
6287             break;
6288           }
6289         case INTERP_KERNEL::NORM_POLYHED:
6290           {
6291             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6292               {
6293                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6294                 ret->pushBackSilent(i);
6295               }
6296             break;
6297           }
6298         default:
6299           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 !");
6300       }
6301     }
6302   updateTime();
6303   return ret.retn();
6304 }
6305
6306 /*!
6307  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6308  * If it is not the case an exception will be thrown.
6309  * This method is fast because the first cell of \a this is used to compute the plane.
6310  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6311  * \param pos output of size at least 3 used to store a point owned of searched plane.
6312  */
6313 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6314 {
6315   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6316     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6317   const int *conn=_nodal_connec->getConstPointer();
6318   const int *connI=_nodal_connec_index->getConstPointer();
6319   const double *coordsPtr=_coords->getConstPointer();
6320   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6321   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6322 }
6323
6324 /*!
6325  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6326  * cells. Currently cells of the following types are treated:
6327  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6328  * For a cell of other type an exception is thrown.
6329  * Space dimension of a 2D mesh can be either 2 or 3.
6330  * The Edge Ratio of a cell \f$t\f$ is: 
6331  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6332  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6333  *  the smallest edge lengths of \f$t\f$.
6334  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6335  *          cells and one time, lying on \a this mesh. The caller is to delete this
6336  *          field using decrRef() as it is no more needed. 
6337  *  \throw If the coordinates array is not set.
6338  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6339  *  \throw If the connectivity data array has more than one component.
6340  *  \throw If the connectivity data array has a named component.
6341  *  \throw If the connectivity index data array has more than one component.
6342  *  \throw If the connectivity index data array has a named component.
6343  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6344  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6345  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6346  */
6347 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6348 {
6349   checkCoherency();
6350   int spaceDim=getSpaceDimension();
6351   int meshDim=getMeshDimension();
6352   if(spaceDim!=2 && spaceDim!=3)
6353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6354   if(meshDim!=2 && meshDim!=3)
6355     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6356   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6357   ret->setMesh(this);
6358   int nbOfCells=getNumberOfCells();
6359   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6360   arr->alloc(nbOfCells,1);
6361   double *pt=arr->getPointer();
6362   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6363   const int *conn=_nodal_connec->getConstPointer();
6364   const int *connI=_nodal_connec_index->getConstPointer();
6365   const double *coo=_coords->getConstPointer();
6366   double tmp[12];
6367   for(int i=0;i<nbOfCells;i++,pt++)
6368     {
6369       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6370       switch(t)
6371       {
6372         case INTERP_KERNEL::NORM_TRI3:
6373           {
6374             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6375             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6376             break;
6377           }
6378         case INTERP_KERNEL::NORM_QUAD4:
6379           {
6380             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6381             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6382             break;
6383           }
6384         case INTERP_KERNEL::NORM_TETRA4:
6385           {
6386             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6387             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6388             break;
6389           }
6390         default:
6391           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6392       }
6393       conn+=connI[i+1]-connI[i];
6394     }
6395   ret->setName("EdgeRatio");
6396   ret->synchronizeTimeWithSupport();
6397   return ret.retn();
6398 }
6399
6400 /*!
6401  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6402  * cells. Currently cells of the following types are treated:
6403  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6404  * For a cell of other type an exception is thrown.
6405  * Space dimension of a 2D mesh can be either 2 or 3.
6406  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6407  *          cells and one time, lying on \a this mesh. The caller is to delete this
6408  *          field using decrRef() as it is no more needed. 
6409  *  \throw If the coordinates array is not set.
6410  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6411  *  \throw If the connectivity data array has more than one component.
6412  *  \throw If the connectivity data array has a named component.
6413  *  \throw If the connectivity index data array has more than one component.
6414  *  \throw If the connectivity index data array has a named component.
6415  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6416  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6417  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6418  */
6419 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6420 {
6421   checkCoherency();
6422   int spaceDim=getSpaceDimension();
6423   int meshDim=getMeshDimension();
6424   if(spaceDim!=2 && spaceDim!=3)
6425     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6426   if(meshDim!=2 && meshDim!=3)
6427     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6428   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6429   ret->setMesh(this);
6430   int nbOfCells=getNumberOfCells();
6431   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6432   arr->alloc(nbOfCells,1);
6433   double *pt=arr->getPointer();
6434   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6435   const int *conn=_nodal_connec->getConstPointer();
6436   const int *connI=_nodal_connec_index->getConstPointer();
6437   const double *coo=_coords->getConstPointer();
6438   double tmp[12];
6439   for(int i=0;i<nbOfCells;i++,pt++)
6440     {
6441       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6442       switch(t)
6443       {
6444         case INTERP_KERNEL::NORM_TRI3:
6445           {
6446             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6447             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6448             break;
6449           }
6450         case INTERP_KERNEL::NORM_QUAD4:
6451           {
6452             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6453             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6454             break;
6455           }
6456         case INTERP_KERNEL::NORM_TETRA4:
6457           {
6458             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6459             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6460             break;
6461           }
6462         default:
6463           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6464       }
6465       conn+=connI[i+1]-connI[i];
6466     }
6467   ret->setName("AspectRatio");
6468   ret->synchronizeTimeWithSupport();
6469   return ret.retn();
6470 }
6471
6472 /*!
6473  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6474  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6475  * treated: INTERP_KERNEL::NORM_QUAD4.
6476  * For a cell of other type an exception is thrown.
6477  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6478  *          cells and one time, lying on \a this mesh. The caller is to delete this
6479  *          field using decrRef() as it is no more needed. 
6480  *  \throw If the coordinates array is not set.
6481  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6482  *  \throw If the connectivity data array has more than one component.
6483  *  \throw If the connectivity data array has a named component.
6484  *  \throw If the connectivity index data array has more than one component.
6485  *  \throw If the connectivity index data array has a named component.
6486  *  \throw If \a this->getMeshDimension() != 2.
6487  *  \throw If \a this->getSpaceDimension() != 3.
6488  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6489  */
6490 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6491 {
6492   checkCoherency();
6493   int spaceDim=getSpaceDimension();
6494   int meshDim=getMeshDimension();
6495   if(spaceDim!=3)
6496     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6497   if(meshDim!=2)
6498     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6499   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6500   ret->setMesh(this);
6501   int nbOfCells=getNumberOfCells();
6502   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6503   arr->alloc(nbOfCells,1);
6504   double *pt=arr->getPointer();
6505   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6506   const int *conn=_nodal_connec->getConstPointer();
6507   const int *connI=_nodal_connec_index->getConstPointer();
6508   const double *coo=_coords->getConstPointer();
6509   double tmp[12];
6510   for(int i=0;i<nbOfCells;i++,pt++)
6511     {
6512       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6513       switch(t)
6514       {
6515         case INTERP_KERNEL::NORM_QUAD4:
6516           {
6517             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6518             *pt=INTERP_KERNEL::quadWarp(tmp);
6519             break;
6520           }
6521         default:
6522           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6523       }
6524       conn+=connI[i+1]-connI[i];
6525     }
6526   ret->setName("Warp");
6527   ret->synchronizeTimeWithSupport();
6528   return ret.retn();
6529 }
6530
6531
6532 /*!
6533  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6534  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6535  * treated: INTERP_KERNEL::NORM_QUAD4.
6536  * For a cell of other type an exception is thrown.
6537  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6538  *          cells and one time, lying on \a this mesh. The caller is to delete this
6539  *          field using decrRef() as it is no more needed. 
6540  *  \throw If the coordinates array is not set.
6541  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6542  *  \throw If the connectivity data array has more than one component.
6543  *  \throw If the connectivity data array has a named component.
6544  *  \throw If the connectivity index data array has more than one component.
6545  *  \throw If the connectivity index data array has a named component.
6546  *  \throw If \a this->getMeshDimension() != 2.
6547  *  \throw If \a this->getSpaceDimension() != 3.
6548  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6549  */
6550 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6551 {
6552   checkCoherency();
6553   int spaceDim=getSpaceDimension();
6554   int meshDim=getMeshDimension();
6555   if(spaceDim!=3)
6556     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6557   if(meshDim!=2)
6558     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6559   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6560   ret->setMesh(this);
6561   int nbOfCells=getNumberOfCells();
6562   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6563   arr->alloc(nbOfCells,1);
6564   double *pt=arr->getPointer();
6565   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6566   const int *conn=_nodal_connec->getConstPointer();
6567   const int *connI=_nodal_connec_index->getConstPointer();
6568   const double *coo=_coords->getConstPointer();
6569   double tmp[12];
6570   for(int i=0;i<nbOfCells;i++,pt++)
6571     {
6572       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6573       switch(t)
6574       {
6575         case INTERP_KERNEL::NORM_QUAD4:
6576           {
6577             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6578             *pt=INTERP_KERNEL::quadSkew(tmp);
6579             break;
6580           }
6581         default:
6582           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6583       }
6584       conn+=connI[i+1]-connI[i];
6585     }
6586   ret->setName("Skew");
6587   ret->synchronizeTimeWithSupport();
6588   return ret.retn();
6589 }
6590
6591 /*!
6592  * 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.
6593  *
6594  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6595  *
6596  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6597  */
6598 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6599 {
6600   checkCoherency();
6601   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6602   ret->setMesh(this);
6603   std::set<INTERP_KERNEL::NormalizedCellType> types;
6604   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6605   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6606   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6607   arr->alloc(nbCells,1);
6608   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6609     {
6610       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6611       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6612       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6613     }
6614   ret->setArray(arr);
6615   ret->setName("Diameter");
6616   return ret.retn();
6617 }
6618
6619 /*!
6620  * This method aggregate the bbox of each cell and put it into bbox parameter.
6621  * 
6622  * \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)
6623  *                         For all other cases this input parameter is ignored.
6624  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6625  * 
6626  * \throw If \a this is not fully set (coordinates and connectivity).
6627  * \throw If a cell in \a this has no valid nodeId.
6628  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6629  */
6630 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6631 {
6632   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6633   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.
6634     return getBoundingBoxForBBTreeFast();
6635   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6636     {
6637       bool presenceOfQuadratic(false);
6638       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6639         {
6640           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6641           if(cm.isQuadratic())
6642             presenceOfQuadratic=true;
6643         }
6644       if(!presenceOfQuadratic)
6645         return getBoundingBoxForBBTreeFast();
6646       if(mDim==2 && sDim==2)
6647         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6648       else
6649         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6650     }
6651   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) !");
6652 }
6653
6654 /*!
6655  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6656  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6657  * 
6658  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6659  * 
6660  * \throw If \a this is not fully set (coordinates and connectivity).
6661  * \throw If a cell in \a this has no valid nodeId.
6662  */
6663 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6664 {
6665   checkFullyDefined();
6666   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6667   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6668   double *bbox(ret->getPointer());
6669   for(int i=0;i<nbOfCells*spaceDim;i++)
6670     {
6671       bbox[2*i]=std::numeric_limits<double>::max();
6672       bbox[2*i+1]=-std::numeric_limits<double>::max();
6673     }
6674   const double *coordsPtr(_coords->getConstPointer());
6675   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6676   for(int i=0;i<nbOfCells;i++)
6677     {
6678       int offset=connI[i]+1;
6679       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6680       for(int j=0;j<nbOfNodesForCell;j++)
6681         {
6682           int nodeId=conn[offset+j];
6683           if(nodeId>=0 && nodeId<nbOfNodes)
6684             {
6685               for(int k=0;k<spaceDim;k++)
6686                 {
6687                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6688                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6689                 }
6690               kk++;
6691             }
6692         }
6693       if(kk==0)
6694         {
6695           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6696           throw INTERP_KERNEL::Exception(oss.str().c_str());
6697         }
6698     }
6699   return ret.retn();
6700 }
6701
6702 /*!
6703  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6704  * useful for 2D meshes having quadratic cells
6705  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6706  * the two extremities of the arc of circle).
6707  * 
6708  * \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)
6709  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6710  * \throw If \a this is not fully defined.
6711  * \throw If \a this is not a mesh with meshDimension equal to 2.
6712  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6713  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6714  */
6715 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6716 {
6717   checkFullyDefined();
6718   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6719   if(spaceDim!=2 || mDim!=2)
6720     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!");
6721   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6722   double *bbox(ret->getPointer());
6723   const double *coords(_coords->getConstPointer());
6724   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6725   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6726     {
6727       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6728       int sz(connI[1]-connI[0]-1);
6729       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6730       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6731       INTERP_KERNEL::QuadraticPolygon *pol(0);
6732       for(int j=0;j<sz;j++)
6733         {
6734           int nodeId(conn[*connI+1+j]);
6735           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6736         }
6737       if(!cm.isQuadratic())
6738         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6739       else
6740         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6741       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6742       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6743     }
6744   return ret.retn();
6745 }
6746
6747 /*!
6748  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6749  * useful for 2D meshes having quadratic cells
6750  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6751  * the two extremities of the arc of circle).
6752  * 
6753  * \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)
6754  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6755  * \throw If \a this is not fully defined.
6756  * \throw If \a this is not a mesh with meshDimension equal to 1.
6757  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6758  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6759  */
6760 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6761 {
6762   checkFullyDefined();
6763   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6764   if(spaceDim!=2 || mDim!=1)
6765     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!");
6766   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6767   double *bbox(ret->getPointer());
6768   const double *coords(_coords->getConstPointer());
6769   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6770   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6771     {
6772       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6773       int sz(connI[1]-connI[0]-1);
6774       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6775       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6776       INTERP_KERNEL::Edge *edge(0);
6777       for(int j=0;j<sz;j++)
6778         {
6779           int nodeId(conn[*connI+1+j]);
6780           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6781         }
6782       if(!cm.isQuadratic())
6783         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6784       else
6785         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6786       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6787       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6788     }
6789   return ret.retn();
6790 }
6791
6792 /// @cond INTERNAL
6793
6794 namespace ParaMEDMEMImpl
6795 {
6796   class ConnReader
6797   {
6798   public:
6799     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6800     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6801   private:
6802     const int *_conn;
6803     int _val;
6804   };
6805
6806   class ConnReader2
6807   {
6808   public:
6809     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6810     bool operator() (const int& pos) { return _conn[pos]==_val; }
6811   private:
6812     const int *_conn;
6813     int _val;
6814   };
6815 }
6816
6817 /// @endcond
6818
6819 /*!
6820  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6821  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6822  * \a this is composed in cell types.
6823  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6824  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6825  * This parameter is kept only for compatibility with other methode listed above.
6826  */
6827 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6828 {
6829   checkConnectivityFullyDefined();
6830   const int *conn=_nodal_connec->getConstPointer();
6831   const int *connI=_nodal_connec_index->getConstPointer();
6832   const int *work=connI;
6833   int nbOfCells=getNumberOfCells();
6834   std::size_t n=getAllGeoTypes().size();
6835   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6836   std::set<INTERP_KERNEL::NormalizedCellType> types;
6837   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6838     {
6839       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6840       if(types.find(typ)!=types.end())
6841         {
6842           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6843           oss << " is not contiguous !";
6844           throw INTERP_KERNEL::Exception(oss.str().c_str());
6845         }
6846       types.insert(typ);
6847       ret[3*i]=typ;
6848       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6849       ret[3*i+1]=(int)std::distance(work,work2);
6850       work=work2;
6851     }
6852   return ret;
6853 }
6854
6855 /*!
6856  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6857  * only for types cell, type node is not managed.
6858  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6859  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6860  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6861  * If 2 or more same geometric type is in \a code and exception is thrown too.
6862  *
6863  * This method firstly checks
6864  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6865  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6866  * an exception is thrown too.
6867  * 
6868  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6869  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6870  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6871  */
6872 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6873 {
6874   if(code.empty())
6875     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6876   std::size_t sz=code.size();
6877   std::size_t n=sz/3;
6878   if(sz%3!=0)
6879     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6880   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6881   int nb=0;
6882   bool isNoPflUsed=true;
6883   for(std::size_t i=0;i<n;i++)
6884     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6885       {
6886         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6887         nb+=code[3*i+1];
6888         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6889           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6890         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6891       }
6892   if(types.size()!=n)
6893     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6894   if(isNoPflUsed)
6895     {
6896       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6897         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6898       if(types.size()==_types.size())
6899         return 0;
6900     }
6901   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6902   ret->alloc(nb,1);
6903   int *retPtr=ret->getPointer();
6904   const int *connI=_nodal_connec_index->getConstPointer();
6905   const int *conn=_nodal_connec->getConstPointer();
6906   int nbOfCells=getNumberOfCells();
6907   const int *i=connI;
6908   int kk=0;
6909   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6910     {
6911       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6912       int offset=(int)std::distance(connI,i);
6913       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6914       int nbOfCellsOfCurType=(int)std::distance(i,j);
6915       if(code[3*kk+2]==-1)
6916         for(int k=0;k<nbOfCellsOfCurType;k++)
6917           *retPtr++=k+offset;
6918       else
6919         {
6920           int idInIdsPerType=code[3*kk+2];
6921           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6922             {
6923               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6924               if(zePfl)
6925                 {
6926                   zePfl->checkAllocated();
6927                   if(zePfl->getNumberOfComponents()==1)
6928                     {
6929                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6930                         {
6931                           if(*k>=0 && *k<nbOfCellsOfCurType)
6932                             *retPtr=(*k)+offset;
6933                           else
6934                             {
6935                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6936                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6937                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6938                             }
6939                         }
6940                     }
6941                   else
6942                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6943                 }
6944               else
6945                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6946             }
6947           else
6948             {
6949               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6950               oss << " should be in [0," << idsPerType.size() << ") !";
6951               throw INTERP_KERNEL::Exception(oss.str().c_str());
6952             }
6953         }
6954       i=j;
6955     }
6956   return ret.retn();
6957 }
6958
6959 /*!
6960  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
6961  * 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.
6962  * 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.
6963  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6964  * 
6965  * \param [in] profile
6966  * \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.
6967  * \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,
6968  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6969  * \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.
6970  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6971  * \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
6972  */
6973 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6974 {
6975   if(!profile)
6976     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6977   if(profile->getNumberOfComponents()!=1)
6978     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6979   checkConnectivityFullyDefined();
6980   const int *conn=_nodal_connec->getConstPointer();
6981   const int *connI=_nodal_connec_index->getConstPointer();
6982   int nbOfCells=getNumberOfCells();
6983   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6984   std::vector<int> typeRangeVals(1);
6985   for(const int *i=connI;i!=connI+nbOfCells;)
6986     {
6987       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6988       if(std::find(types.begin(),types.end(),curType)!=types.end())
6989         {
6990           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6991         }
6992       types.push_back(curType);
6993       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6994       typeRangeVals.push_back((int)std::distance(connI,i));
6995     }
6996   //
6997   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6998   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6999   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
7000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
7001   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
7002   //
7003   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
7004   code.resize(3*nbOfCastsFinal);
7005   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
7006   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
7007   for(int i=0;i<nbOfCastsFinal;i++)
7008     {
7009       int castId=castsPresent->getIJ(i,0);
7010       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
7011       idsInPflPerType2.push_back(tmp3);
7012       code[3*i]=(int)types[castId];
7013       code[3*i+1]=tmp3->getNumberOfTuples();
7014       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7015       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
7016         {
7017           tmp4->copyStringInfoFrom(*profile);
7018           idsPerType2.push_back(tmp4);
7019           code[3*i+2]=(int)idsPerType2.size()-1;
7020         }
7021       else
7022         {
7023           code[3*i+2]=-1;
7024         }
7025     }
7026   std::size_t sz2=idsInPflPerType2.size();
7027   idsInPflPerType.resize(sz2);
7028   for(std::size_t i=0;i<sz2;i++)
7029     {
7030       DataArrayInt *locDa=idsInPflPerType2[i];
7031       locDa->incrRef();
7032       idsInPflPerType[i]=locDa;
7033     }
7034   std::size_t sz=idsPerType2.size();
7035   idsPerType.resize(sz);
7036   for(std::size_t i=0;i<sz;i++)
7037     {
7038       DataArrayInt *locDa=idsPerType2[i];
7039       locDa->incrRef();
7040       idsPerType[i]=locDa;
7041     }
7042 }
7043
7044 /*!
7045  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7046  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7047  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7048  * 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.
7049  */
7050 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7051 {
7052   checkFullyDefined();
7053   nM1LevMesh->checkFullyDefined();
7054   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7055     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7056   if(_coords!=nM1LevMesh->getCoords())
7057     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7058   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7059   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7060   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7061   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7062   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7063   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7064   tmp->setConnectivity(tmp0,tmp1);
7065   tmp->renumberCells(ret0->getConstPointer(),false);
7066   revDesc=tmp->getNodalConnectivity();
7067   revDescIndx=tmp->getNodalConnectivityIndex();
7068   DataArrayInt *ret=0;
7069   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7070     {
7071       int tmp2;
7072       ret->getMaxValue(tmp2);
7073       ret->decrRef();
7074       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7075       throw INTERP_KERNEL::Exception(oss.str().c_str());
7076     }
7077   nM1LevMeshIds=ret;
7078   //
7079   revDesc->incrRef();
7080   revDescIndx->incrRef();
7081   ret1->incrRef();
7082   ret0->incrRef();
7083   meshnM1Old2New=ret0;
7084   return ret1;
7085 }
7086
7087 /*!
7088  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7089  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7090  * in "Old to New" mode.
7091  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7092  *          this array using decrRef() as it is no more needed.
7093  *  \throw If the nodal connectivity of cells is not defined.
7094  */
7095 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7096 {
7097   checkConnectivityFullyDefined();
7098   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7099   renumberCells(ret->getConstPointer(),false);
7100   return ret.retn();
7101 }
7102
7103 /*!
7104  * This methods checks that cells are sorted by their types.
7105  * This method makes asumption (no check) that connectivity is correctly set before calling.
7106  */
7107 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7108 {
7109   checkFullyDefined();
7110   const int *conn=_nodal_connec->getConstPointer();
7111   const int *connI=_nodal_connec_index->getConstPointer();
7112   int nbOfCells=getNumberOfCells();
7113   std::set<INTERP_KERNEL::NormalizedCellType> types;
7114   for(const int *i=connI;i!=connI+nbOfCells;)
7115     {
7116       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7117       if(types.find(curType)!=types.end())
7118         return false;
7119       types.insert(curType);
7120       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7121     }
7122   return true;
7123 }
7124
7125 /*!
7126  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7127  * The geometric type order is specified by MED file.
7128  * 
7129  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7130  */
7131 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7132 {
7133   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7134 }
7135
7136 /*!
7137  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7138  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7139  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7140  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7141  */
7142 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7143 {
7144   checkFullyDefined();
7145   const int *conn=_nodal_connec->getConstPointer();
7146   const int *connI=_nodal_connec_index->getConstPointer();
7147   int nbOfCells=getNumberOfCells();
7148   if(nbOfCells==0)
7149     return true;
7150   int lastPos=-1;
7151   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7152   for(const int *i=connI;i!=connI+nbOfCells;)
7153     {
7154       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7155       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7156       if(isTypeExists!=orderEnd)
7157         {
7158           int pos=(int)std::distance(orderBg,isTypeExists);
7159           if(pos<=lastPos)
7160             return false;
7161           lastPos=pos;
7162           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7163         }
7164       else
7165         {
7166           if(sg.find(curType)==sg.end())
7167             {
7168               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7169               sg.insert(curType);
7170             }
7171           else
7172             return false;
7173         }
7174     }
7175   return true;
7176 }
7177
7178 /*!
7179  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7180  * 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
7181  * 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'.
7182  */
7183 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7184 {
7185   checkConnectivityFullyDefined();
7186   int nbOfCells=getNumberOfCells();
7187   const int *conn=_nodal_connec->getConstPointer();
7188   const int *connI=_nodal_connec_index->getConstPointer();
7189   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7190   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7191   tmpa->alloc(nbOfCells,1);
7192   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7193   tmpb->fillWithZero();
7194   int *tmp=tmpa->getPointer();
7195   int *tmp2=tmpb->getPointer();
7196   for(const int *i=connI;i!=connI+nbOfCells;i++)
7197     {
7198       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7199       if(where!=orderEnd)
7200         {
7201           int pos=(int)std::distance(orderBg,where);
7202           tmp2[pos]++;
7203           tmp[std::distance(connI,i)]=pos;
7204         }
7205       else
7206         {
7207           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7208           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7209           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7210           throw INTERP_KERNEL::Exception(oss.str().c_str());
7211         }
7212     }
7213   nbPerType=tmpb.retn();
7214   return tmpa.retn();
7215 }
7216
7217 /*!
7218  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7219  *
7220  * \return a new object containing the old to new correspondance.
7221  *
7222  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7223  */
7224 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7225 {
7226   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7227 }
7228
7229 /*!
7230  * 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.
7231  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7232  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7233  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7234  */
7235 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7236 {
7237   DataArrayInt *nbPerType=0;
7238   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7239   nbPerType->decrRef();
7240   return tmpa->buildPermArrPerLevel();
7241 }
7242
7243 /*!
7244  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7245  * The number of cells remains unchanged after the call of this method.
7246  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7247  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7248  *
7249  * \return the array giving the correspondance old to new.
7250  */
7251 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7252 {
7253   checkFullyDefined();
7254   computeTypes();
7255   const int *conn=_nodal_connec->getConstPointer();
7256   const int *connI=_nodal_connec_index->getConstPointer();
7257   int nbOfCells=getNumberOfCells();
7258   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7259   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7260     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7261       {
7262         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7263         types.push_back(curType);
7264         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7265       }
7266   DataArrayInt *ret=DataArrayInt::New();
7267   ret->alloc(nbOfCells,1);
7268   int *retPtr=ret->getPointer();
7269   std::fill(retPtr,retPtr+nbOfCells,-1);
7270   int newCellId=0;
7271   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7272     {
7273       for(const int *i=connI;i!=connI+nbOfCells;i++)
7274         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7275           retPtr[std::distance(connI,i)]=newCellId++;
7276     }
7277   renumberCells(retPtr,false);
7278   return ret;
7279 }
7280
7281 /*!
7282  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7283  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7284  * This method makes asumption that connectivity is correctly set before calling.
7285  */
7286 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7287 {
7288   checkConnectivityFullyDefined();
7289   const int *conn=_nodal_connec->getConstPointer();
7290   const int *connI=_nodal_connec_index->getConstPointer();
7291   int nbOfCells=getNumberOfCells();
7292   std::vector<MEDCouplingUMesh *> ret;
7293   for(const int *i=connI;i!=connI+nbOfCells;)
7294     {
7295       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7296       int beginCellId=(int)std::distance(connI,i);
7297       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7298       int endCellId=(int)std::distance(connI,i);
7299       int sz=endCellId-beginCellId;
7300       int *cells=new int[sz];
7301       for(int j=0;j<sz;j++)
7302         cells[j]=beginCellId+j;
7303       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7304       delete [] cells;
7305       ret.push_back(m);
7306     }
7307   return ret;
7308 }
7309
7310 /*!
7311  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7312  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7313  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7314  *
7315  * \return a newly allocated instance, that the caller must manage.
7316  * \throw If \a this contains more than one geometric type.
7317  * \throw If the nodal connectivity of \a this is not fully defined.
7318  * \throw If the internal data is not coherent.
7319  */
7320 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7321 {
7322   checkConnectivityFullyDefined();
7323   if(_types.size()!=1)
7324     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7325   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7326   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7327   ret->setCoords(getCoords());
7328   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7329   if(retC)
7330     {
7331       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7332       retC->setNodalConnectivity(c);
7333     }
7334   else
7335     {
7336       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7337       if(!retD)
7338         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7339       DataArrayInt *c=0,*ci=0;
7340       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7341       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7342       retD->setNodalConnectivity(cs,cis);
7343     }
7344   return ret.retn();
7345 }
7346
7347 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7348 {
7349   checkConnectivityFullyDefined();
7350   if(_types.size()!=1)
7351     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7352   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7353   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7354   if(cm.isDynamic())
7355     {
7356       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7357       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7358       throw INTERP_KERNEL::Exception(oss.str().c_str());
7359     }
7360   int nbCells=getNumberOfCells();
7361   int typi=(int)typ;
7362   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7363   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7364   int *outPtr=connOut->getPointer();
7365   const int *conn=_nodal_connec->begin();
7366   const int *connI=_nodal_connec_index->begin();
7367   nbNodesPerCell++;
7368   for(int i=0;i<nbCells;i++,connI++)
7369     {
7370       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7371         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7372       else
7373         {
7374           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 << ") !";
7375           throw INTERP_KERNEL::Exception(oss.str().c_str());
7376         }
7377     }
7378   return connOut.retn();
7379 }
7380
7381 /*!
7382  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7383  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7384  * \param nodalConn
7385  * \param nodalConnI
7386  */
7387 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7388 {
7389   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7390   checkConnectivityFullyDefined();
7391   if(_types.size()!=1)
7392     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7393   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7394   if(lgth<nbCells)
7395     throw INTERP_KERNEL::Exception(msg0);
7396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7397   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7398   int *cp(c->getPointer()),*cip(ci->getPointer());
7399   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7400   cip[0]=0;
7401   for(int i=0;i<nbCells;i++,cip++,incip++)
7402     {
7403       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7404       int delta(stop-strt);
7405       if(delta>=1)
7406         {
7407           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7408             cp=std::copy(incp+strt,incp+stop,cp);
7409           else
7410             throw INTERP_KERNEL::Exception(msg0);
7411         }
7412       else
7413         throw INTERP_KERNEL::Exception(msg0);
7414       cip[1]=cip[0]+delta;
7415     }
7416   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7417 }
7418
7419 /*!
7420  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7421  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7422  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7423  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7424  * are not used here to avoid the build of big permutation array.
7425  *
7426  * \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
7427  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7428  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7429  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7430  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7431  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7432  * \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
7433  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7434  */
7435 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7436                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7437                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7438 {
7439   std::vector<const MEDCouplingUMesh *> ms2;
7440   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7441     if(*it)
7442       {
7443         (*it)->checkConnectivityFullyDefined();
7444         ms2.push_back(*it);
7445       }
7446   if(ms2.empty())
7447     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7448   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7449   int meshDim=ms2[0]->getMeshDimension();
7450   std::vector<const MEDCouplingUMesh *> m1ssm;
7451   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7452   //
7453   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7454   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7455   int fake=0,rk=0;
7456   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7457   ret1->alloc(0,1); ret2->alloc(0,1);
7458   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7459     {
7460       if(meshDim!=(*it)->getMeshDimension())
7461         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7462       if(refCoo!=(*it)->getCoords())
7463         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7464       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7465       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7466       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7467       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7468         {
7469           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7470           m1ssmSingleAuto.push_back(singleCell);
7471           m1ssmSingle.push_back(singleCell);
7472           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7473         }
7474     }
7475   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7476   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7477   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7478   for(std::size_t i=0;i<m1ssm.size();i++)
7479     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7480   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7481   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7482   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7483   return ret0.retn();
7484 }
7485
7486 /*!
7487  * This method returns a newly created DataArrayInt instance.
7488  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7489  */
7490 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7491 {
7492   checkFullyDefined();
7493   const int *conn=_nodal_connec->getConstPointer();
7494   const int *connIndex=_nodal_connec_index->getConstPointer();
7495   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7496   for(const int *w=begin;w!=end;w++)
7497     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7498       ret->pushBackSilent(*w);
7499   return ret.retn();
7500 }
7501
7502 /*!
7503  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7504  * are in [0:getNumberOfCells())
7505  */
7506 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7507 {
7508   checkFullyDefined();
7509   const int *conn=_nodal_connec->getConstPointer();
7510   const int *connI=_nodal_connec_index->getConstPointer();
7511   int nbOfCells=getNumberOfCells();
7512   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7513   int *tmp=new int[nbOfCells];
7514   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7515     {
7516       int j=0;
7517       for(const int *i=connI;i!=connI+nbOfCells;i++)
7518         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7519           tmp[std::distance(connI,i)]=j++;
7520     }
7521   DataArrayInt *ret=DataArrayInt::New();
7522   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7523   ret->copyStringInfoFrom(*da);
7524   int *retPtr=ret->getPointer();
7525   const int *daPtr=da->getConstPointer();
7526   int nbOfElems=da->getNbOfElems();
7527   for(int k=0;k<nbOfElems;k++)
7528     retPtr[k]=tmp[daPtr[k]];
7529   delete [] tmp;
7530   return ret;
7531 }
7532
7533 /*!
7534  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7535  * This method \b works \b for mesh sorted by type.
7536  * cells whose ids is in 'idsPerGeoType' array.
7537  * This method conserves coords and name of mesh.
7538  */
7539 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7540 {
7541   std::vector<int> code=getDistributionOfTypes();
7542   std::size_t nOfTypesInThis=code.size()/3;
7543   int sz=0,szOfType=0;
7544   for(std::size_t i=0;i<nOfTypesInThis;i++)
7545     {
7546       if(code[3*i]!=type)
7547         sz+=code[3*i+1];
7548       else
7549         szOfType=code[3*i+1];
7550     }
7551   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7552     if(*work<0 || *work>=szOfType)
7553       {
7554         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7555         oss << ". It should be in [0," << szOfType << ") !";
7556         throw INTERP_KERNEL::Exception(oss.str().c_str());
7557       }
7558   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7559   int *idsPtr=idsTokeep->getPointer();
7560   int offset=0;
7561   for(std::size_t i=0;i<nOfTypesInThis;i++)
7562     {
7563       if(code[3*i]!=type)
7564         for(int j=0;j<code[3*i+1];j++)
7565           *idsPtr++=offset+j;
7566       else
7567         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7568       offset+=code[3*i+1];
7569     }
7570   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7571   ret->copyTinyInfoFrom(this);
7572   return ret.retn();
7573 }
7574
7575 /*!
7576  * This method returns a vector of size 'this->getNumberOfCells()'.
7577  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7578  */
7579 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7580 {
7581   int ncell=getNumberOfCells();
7582   std::vector<bool> ret(ncell);
7583   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7584   const int *c=getNodalConnectivity()->getConstPointer();
7585   for(int i=0;i<ncell;i++)
7586     {
7587       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7588       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7589       ret[i]=cm.isQuadratic();
7590     }
7591   return ret;
7592 }
7593
7594 /*!
7595  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7596  */
7597 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7598 {
7599   if(other->getType()!=UNSTRUCTURED)
7600     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7601   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7602   return MergeUMeshes(this,otherC);
7603 }
7604
7605 /*!
7606  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7607  * computed by averaging coordinates of cell nodes, so this method is not a right
7608  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7609  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7610  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7611  *          components. The caller is to delete this array using decrRef() as it is
7612  *          no more needed.
7613  *  \throw If the coordinates array is not set.
7614  *  \throw If the nodal connectivity of cells is not defined.
7615  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7616  */
7617 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7618 {
7619   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7620   int spaceDim=getSpaceDimension();
7621   int nbOfCells=getNumberOfCells();
7622   ret->alloc(nbOfCells,spaceDim);
7623   ret->copyStringInfoFrom(*getCoords());
7624   double *ptToFill=ret->getPointer();
7625   const int *nodal=_nodal_connec->getConstPointer();
7626   const int *nodalI=_nodal_connec_index->getConstPointer();
7627   const double *coor=_coords->getConstPointer();
7628   for(int i=0;i<nbOfCells;i++)
7629     {
7630       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7631       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7632       ptToFill+=spaceDim;
7633     }
7634   return ret.retn();
7635 }
7636
7637 /*!
7638  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7639  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7640  * 
7641  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7642  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7643  * 
7644  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7645  * \throw If \a this is not fully defined (coordinates and connectivity)
7646  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7647  */
7648 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7649 {
7650   checkFullyDefined();
7651   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7652   int spaceDim=getSpaceDimension();
7653   int nbOfCells=getNumberOfCells();
7654   int nbOfNodes=getNumberOfNodes();
7655   ret->alloc(nbOfCells,spaceDim);
7656   double *ptToFill=ret->getPointer();
7657   const int *nodal=_nodal_connec->getConstPointer();
7658   const int *nodalI=_nodal_connec_index->getConstPointer();
7659   const double *coor=_coords->getConstPointer();
7660   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7661     {
7662       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7663       std::fill(ptToFill,ptToFill+spaceDim,0.);
7664       if(type!=INTERP_KERNEL::NORM_POLYHED)
7665         {
7666           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7667             {
7668               if(*conn>=0 && *conn<nbOfNodes)
7669                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7670               else
7671                 {
7672                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7673                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7674                 }
7675             }
7676           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7677           if(nbOfNodesInCell>0)
7678             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7679           else
7680             {
7681               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7682               throw INTERP_KERNEL::Exception(oss.str().c_str());
7683             }
7684         }
7685       else
7686         {
7687           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7688           s.erase(-1);
7689           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7690             {
7691               if(*it>=0 && *it<nbOfNodes)
7692                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7693               else
7694                 {
7695                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7696                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7697                 }
7698             }
7699           if(!s.empty())
7700             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7701           else
7702             {
7703               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7704               throw INTERP_KERNEL::Exception(oss.str().c_str());
7705             }
7706         }
7707     }
7708   return ret.retn();
7709 }
7710
7711 /*!
7712  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7713  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7714  * are specified via an array of cell ids. 
7715  *  \warning Validity of the specified cell ids is not checked! 
7716  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7717  *  \param [in] begin - an array of cell ids of interest.
7718  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7719  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7720  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7721  *          caller is to delete this array using decrRef() as it is no more needed. 
7722  *  \throw If the coordinates array is not set.
7723  *  \throw If the nodal connectivity of cells is not defined.
7724  *
7725  *  \if ENABLE_EXAMPLES
7726  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7727  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7728  *  \endif
7729  */
7730 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7731 {
7732   DataArrayDouble *ret=DataArrayDouble::New();
7733   int spaceDim=getSpaceDimension();
7734   int nbOfTuple=(int)std::distance(begin,end);
7735   ret->alloc(nbOfTuple,spaceDim);
7736   double *ptToFill=ret->getPointer();
7737   double *tmp=new double[spaceDim];
7738   const int *nodal=_nodal_connec->getConstPointer();
7739   const int *nodalI=_nodal_connec_index->getConstPointer();
7740   const double *coor=_coords->getConstPointer();
7741   for(const int *w=begin;w!=end;w++)
7742     {
7743       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7744       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7745       ptToFill+=spaceDim;
7746     }
7747   delete [] tmp;
7748   return ret;
7749 }
7750
7751 /*!
7752  * 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".
7753  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7754  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7755  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7756  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7757  * 
7758  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7759  * \throw If spaceDim!=3 or meshDim!=2.
7760  * \throw If connectivity of \a this is invalid.
7761  * \throw If connectivity of a cell in \a this points to an invalid node.
7762  */
7763 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7764 {
7765   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7766   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7767   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7768     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7769   ret->alloc(nbOfCells,4);
7770   double *retPtr(ret->getPointer());
7771   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7772   const double *coor(_coords->begin());
7773   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7774     {
7775       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7776       if(nodalI[1]-nodalI[0]>=3)
7777         {
7778           for(int j=0;j<3;j++)
7779             {
7780               int nodeId(nodal[nodalI[0]+1+j]);
7781               if(nodeId>=0 && nodeId<nbOfNodes)
7782                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7783               else
7784                 {
7785                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7786                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7787                 }
7788             }
7789         }
7790       else
7791         {
7792           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7793           throw INTERP_KERNEL::Exception(oss.str().c_str());
7794         }
7795       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7796       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7797     }
7798   return ret.retn();
7799 }
7800
7801 /*!
7802  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7803  * 
7804  */
7805 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7806 {
7807   if(!da)
7808     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7809   da->checkAllocated();
7810   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7811   ret->setCoords(da);
7812   int nbOfTuples=da->getNumberOfTuples();
7813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7814   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7815   c->alloc(2*nbOfTuples,1);
7816   cI->alloc(nbOfTuples+1,1);
7817   int *cp=c->getPointer();
7818   int *cip=cI->getPointer();
7819   *cip++=0;
7820   for(int i=0;i<nbOfTuples;i++)
7821     {
7822       *cp++=INTERP_KERNEL::NORM_POINT1;
7823       *cp++=i;
7824       *cip++=2*(i+1);
7825     }
7826   ret->setConnectivity(c,cI,true);
7827   return ret.retn();
7828 }
7829 /*!
7830  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7831  * Cells and nodes of
7832  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7833  *  \param [in] mesh1 - the first mesh.
7834  *  \param [in] mesh2 - the second mesh.
7835  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7836  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7837  *          is no more needed.
7838  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7839  *  \throw If the coordinates array is not set in none of the meshes.
7840  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7841  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7842  */
7843 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7844 {
7845   std::vector<const MEDCouplingUMesh *> tmp(2);
7846   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7847   return MergeUMeshes(tmp);
7848 }
7849
7850 /*!
7851  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7852  * Cells and nodes of
7853  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7854  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7855  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7856  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7857  *          is no more needed.
7858  *  \throw If \a a.size() == 0.
7859  *  \throw If \a a[ *i* ] == NULL.
7860  *  \throw If the coordinates array is not set in none of the meshes.
7861  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7862  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7863  */
7864 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7865 {
7866   std::size_t sz=a.size();
7867   if(sz==0)
7868     return MergeUMeshesLL(a);
7869   for(std::size_t ii=0;ii<sz;ii++)
7870     if(!a[ii])
7871       {
7872         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7873         throw INTERP_KERNEL::Exception(oss.str().c_str());
7874       }
7875   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7876   std::vector< const MEDCouplingUMesh * > aa(sz);
7877   int spaceDim=-3;
7878   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7879     {
7880       const MEDCouplingUMesh *cur=a[i];
7881       const DataArrayDouble *coo=cur->getCoords();
7882       if(coo)
7883         spaceDim=coo->getNumberOfComponents();
7884     }
7885   if(spaceDim==-3)
7886     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7887   for(std::size_t i=0;i<sz;i++)
7888     {
7889       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7890       aa[i]=bb[i];
7891     }
7892   return MergeUMeshesLL(aa);
7893 }
7894
7895 /// @cond INTERNAL
7896
7897 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7898 {
7899   if(a.empty())
7900     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7901   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7902   int meshDim=(*it)->getMeshDimension();
7903   int nbOfCells=(*it)->getNumberOfCells();
7904   int meshLgth=(*it++)->getMeshLength();
7905   for(;it!=a.end();it++)
7906     {
7907       if(meshDim!=(*it)->getMeshDimension())
7908         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7909       nbOfCells+=(*it)->getNumberOfCells();
7910       meshLgth+=(*it)->getMeshLength();
7911     }
7912   std::vector<const MEDCouplingPointSet *> aps(a.size());
7913   std::copy(a.begin(),a.end(),aps.begin());
7914   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7915   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7916   ret->setCoords(pts);
7917   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7918   c->alloc(meshLgth,1);
7919   int *cPtr=c->getPointer();
7920   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7921   cI->alloc(nbOfCells+1,1);
7922   int *cIPtr=cI->getPointer();
7923   *cIPtr++=0;
7924   int offset=0;
7925   int offset2=0;
7926   for(it=a.begin();it!=a.end();it++)
7927     {
7928       int curNbOfCell=(*it)->getNumberOfCells();
7929       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7930       const int *curC=(*it)->_nodal_connec->getConstPointer();
7931       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7932       for(int j=0;j<curNbOfCell;j++)
7933         {
7934           const int *src=curC+curCI[j];
7935           *cPtr++=*src++;
7936           for(;src!=curC+curCI[j+1];src++,cPtr++)
7937             {
7938               if(*src!=-1)
7939                 *cPtr=*src+offset2;
7940               else
7941                 *cPtr=-1;
7942             }
7943         }
7944       offset+=curCI[curNbOfCell];
7945       offset2+=(*it)->getNumberOfNodes();
7946     }
7947   //
7948   ret->setConnectivity(c,cI,true);
7949   return ret.retn();
7950 }
7951
7952 /// @endcond
7953
7954 /*!
7955  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7956  * dimension and sharing the node coordinates array.
7957  * All cells of the first mesh precede all cells of the second mesh
7958  * within the result mesh. 
7959  *  \param [in] mesh1 - the first mesh.
7960  *  \param [in] mesh2 - the second mesh.
7961  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7962  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7963  *          is no more needed.
7964  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7965  *  \throw If the meshes do not share the node coordinates array.
7966  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7967  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7968  */
7969 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7970 {
7971   std::vector<const MEDCouplingUMesh *> tmp(2);
7972   tmp[0]=mesh1; tmp[1]=mesh2;
7973   return MergeUMeshesOnSameCoords(tmp);
7974 }
7975
7976 /*!
7977  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7978  * dimension and sharing the node coordinates array.
7979  * All cells of the *i*-th mesh precede all cells of the
7980  * (*i*+1)-th mesh within the result mesh.
7981  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7982  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7983  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7984  *          is no more needed.
7985  *  \throw If \a a.size() == 0.
7986  *  \throw If \a a[ *i* ] == NULL.
7987  *  \throw If the meshes do not share the node coordinates array.
7988  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7989  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7990  */
7991 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7992 {
7993   if(meshes.empty())
7994     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7995   for(std::size_t ii=0;ii<meshes.size();ii++)
7996     if(!meshes[ii])
7997       {
7998         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7999         throw INTERP_KERNEL::Exception(oss.str().c_str());
8000       }
8001   const DataArrayDouble *coords=meshes.front()->getCoords();
8002   int meshDim=meshes.front()->getMeshDimension();
8003   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
8004   int meshLgth=0;
8005   int meshIndexLgth=0;
8006   for(;iter!=meshes.end();iter++)
8007     {
8008       if(coords!=(*iter)->getCoords())
8009         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8010       if(meshDim!=(*iter)->getMeshDimension())
8011         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8012       meshLgth+=(*iter)->getMeshLength();
8013       meshIndexLgth+=(*iter)->getNumberOfCells();
8014     }
8015   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
8016   nodal->alloc(meshLgth,1);
8017   int *nodalPtr=nodal->getPointer();
8018   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
8019   nodalIndex->alloc(meshIndexLgth+1,1);
8020   int *nodalIndexPtr=nodalIndex->getPointer();
8021   int offset=0;
8022   for(iter=meshes.begin();iter!=meshes.end();iter++)
8023     {
8024       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8025       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8026       int nbOfCells=(*iter)->getNumberOfCells();
8027       int meshLgth2=(*iter)->getMeshLength();
8028       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8029       if(iter!=meshes.begin())
8030         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8031       else
8032         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8033       offset+=meshLgth2;
8034     }
8035   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8036   ret->setName("merge");
8037   ret->setMeshDimension(meshDim);
8038   ret->setConnectivity(nodal,nodalIndex,true);
8039   ret->setCoords(coords);
8040   return ret;
8041 }
8042
8043 /*!
8044  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8045  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8046  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8047  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8048  * New" mode are returned for each input mesh.
8049  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8050  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8051  *          valid values [0,1,2], see zipConnectivityTraducer().
8052  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8053  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8054  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8055  *          no more needed.
8056  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8057  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8058  *          is no more needed.
8059  *  \throw If \a meshes.size() == 0.
8060  *  \throw If \a meshes[ *i* ] == NULL.
8061  *  \throw If the meshes do not share the node coordinates array.
8062  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8063  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8064  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8065  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8066  */
8067 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8068 {
8069   //All checks are delegated to MergeUMeshesOnSameCoords
8070   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8071   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8072   corr.resize(meshes.size());
8073   std::size_t nbOfMeshes=meshes.size();
8074   int offset=0;
8075   const int *o2nPtr=o2n->getConstPointer();
8076   for(std::size_t i=0;i<nbOfMeshes;i++)
8077     {
8078       DataArrayInt *tmp=DataArrayInt::New();
8079       int curNbOfCells=meshes[i]->getNumberOfCells();
8080       tmp->alloc(curNbOfCells,1);
8081       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8082       offset+=curNbOfCells;
8083       tmp->setName(meshes[i]->getName());
8084       corr[i]=tmp;
8085     }
8086   return ret.retn();
8087 }
8088
8089 /*!
8090  * Makes all given meshes share the nodal connectivity array. The common connectivity
8091  * array is created by concatenating the connectivity arrays of all given meshes. All
8092  * the given meshes must be of the same space dimension but dimension of cells **can
8093  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8094  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8095  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8096  *  \param [in,out] meshes - a vector of meshes to update.
8097  *  \throw If any of \a meshes is NULL.
8098  *  \throw If the coordinates array is not set in any of \a meshes.
8099  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8100  *  \throw If \a meshes are of different space dimension.
8101  */
8102 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8103 {
8104   std::size_t sz=meshes.size();
8105   if(sz==0 || sz==1)
8106     return;
8107   std::vector< const DataArrayDouble * > coords(meshes.size());
8108   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8109   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8110     {
8111       if((*it))
8112         {
8113           (*it)->checkConnectivityFullyDefined();
8114           const DataArrayDouble *coo=(*it)->getCoords();
8115           if(coo)
8116             *it2=coo;
8117           else
8118             {
8119               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8120               oss << " has no coordinate array defined !";
8121               throw INTERP_KERNEL::Exception(oss.str().c_str());
8122             }
8123         }
8124       else
8125         {
8126           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8127           oss << " is null !";
8128           throw INTERP_KERNEL::Exception(oss.str().c_str());
8129         }
8130     }
8131   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8132   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8133   int offset=(*it)->getNumberOfNodes();
8134   (*it++)->setCoords(res);
8135   for(;it!=meshes.end();it++)
8136     {
8137       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8138       (*it)->setCoords(res);
8139       (*it)->shiftNodeNumbersInConn(offset);
8140       offset+=oldNumberOfNodes;
8141     }
8142 }
8143
8144 /*!
8145  * Merges nodes coincident with a given precision within all given meshes that share
8146  * the nodal connectivity array. The given meshes **can be of different** mesh
8147  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8148  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8149  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8150  *  \param [in,out] meshes - a vector of meshes to update.
8151  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8152  *  \throw If any of \a meshes is NULL.
8153  *  \throw If the \a meshes do not share the same node coordinates array.
8154  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8155  */
8156 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8157 {
8158   if(meshes.empty())
8159     return ;
8160   std::set<const DataArrayDouble *> s;
8161   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8162     {
8163       if(*it)
8164         s.insert((*it)->getCoords());
8165       else
8166         {
8167           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 !";
8168           throw INTERP_KERNEL::Exception(oss.str().c_str());
8169         }
8170     }
8171   if(s.size()!=1)
8172     {
8173       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 !";
8174       throw INTERP_KERNEL::Exception(oss.str().c_str());
8175     }
8176   const DataArrayDouble *coo=*(s.begin());
8177   if(!coo)
8178     return;
8179   //
8180   DataArrayInt *comm,*commI;
8181   coo->findCommonTuples(eps,-1,comm,commI);
8182   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8183   int oldNbOfNodes=coo->getNumberOfTuples();
8184   int newNbOfNodes;
8185   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8186   if(oldNbOfNodes==newNbOfNodes)
8187     return ;
8188   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8189   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8190     {
8191       (*it)->renumberNodesInConn(o2n->getConstPointer());
8192       (*it)->setCoords(newCoords);
8193     } 
8194 }
8195
8196 /*!
8197  * 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.
8198  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8199  * \param isQuad specifies the policy of connectivity.
8200  * @ret in/out parameter in which the result will be append
8201  */
8202 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8203 {
8204   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8205   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8206   ret.push_back(cm.getExtrudedType());
8207   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8208   switch(flatType)
8209   {
8210     case INTERP_KERNEL::NORM_POINT1:
8211       {
8212         ret.push_back(connBg[1]);
8213         ret.push_back(connBg[1]+nbOfNodesPerLev);
8214         break;
8215       }
8216     case INTERP_KERNEL::NORM_SEG2:
8217       {
8218         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8219         ret.insert(ret.end(),conn,conn+4);
8220         break;
8221       }
8222     case INTERP_KERNEL::NORM_SEG3:
8223       {
8224         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8225         ret.insert(ret.end(),conn,conn+8);
8226         break;
8227       }
8228     case INTERP_KERNEL::NORM_QUAD4:
8229       {
8230         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8231         ret.insert(ret.end(),conn,conn+8);
8232         break;
8233       }
8234     case INTERP_KERNEL::NORM_TRI3:
8235       {
8236         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8237         ret.insert(ret.end(),conn,conn+6);
8238         break;
8239       }
8240     case INTERP_KERNEL::NORM_TRI6:
8241       {
8242         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,
8243           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8244         ret.insert(ret.end(),conn,conn+15);
8245         break;
8246       }
8247     case INTERP_KERNEL::NORM_QUAD8:
8248       {
8249         int conn[20]={
8250           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8251           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8252           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8253         };
8254         ret.insert(ret.end(),conn,conn+20);
8255         break;
8256       }
8257     case INTERP_KERNEL::NORM_POLYGON:
8258       {
8259         std::back_insert_iterator< std::vector<int> > ii(ret);
8260         std::copy(connBg+1,connEnd,ii);
8261         *ii++=-1;
8262         std::reverse_iterator<const int *> rConnBg(connEnd);
8263         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8264         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8265         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8266         for(std::size_t i=0;i<nbOfRadFaces;i++)
8267           {
8268             *ii++=-1;
8269             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8270             std::copy(conn,conn+4,ii);
8271           }
8272         break;
8273       }
8274     default:
8275       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8276   }
8277 }
8278
8279 /*!
8280  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8281  */
8282 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8283 {
8284   std::size_t i, ip1;
8285   double v[3]={0.,0.,0.};
8286   std::size_t sz=std::distance(begin,end);
8287   if(isQuadratic)
8288     sz/=2;
8289   for(i=0;i<sz;i++)
8290     {
8291       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];
8292       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8293       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8294     }
8295   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8296
8297   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8298   // SEG3 forming a circle):
8299   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8300     {
8301       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8302       for(std::size_t j=0;j<sz;j++)
8303         {
8304           if (j%2)  // current point i is quadratic, next point i+1 is standard
8305             {
8306               i = sz+j;
8307               ip1 = (j+1)%sz; // ip1 = "i+1"
8308             }
8309           else      // current point i is standard, next point i+1 is quadratic
8310             {
8311               i = j;
8312               ip1 = j+sz;
8313             }
8314           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8315           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8316           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8317         }
8318       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8319     }
8320   return (ret>0.);
8321 }
8322
8323 /*!
8324  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8325  */
8326 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8327 {
8328   std::vector<std::pair<int,int> > edges;
8329   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8330   const int *bgFace=begin;
8331   for(std::size_t i=0;i<nbOfFaces;i++)
8332     {
8333       const int *endFace=std::find(bgFace+1,end,-1);
8334       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8335       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8336         {
8337           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8338           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8339             return false;
8340           edges.push_back(p1);
8341         }
8342       bgFace=endFace+1;
8343     }
8344   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8345 }
8346
8347 /*!
8348  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8349  */
8350 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8351 {
8352   double vec0[3],vec1[3];
8353   std::size_t sz=std::distance(begin,end);
8354   if(sz%2!=0)
8355     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8356   int nbOfNodes=(int)sz/2;
8357   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8358   const double *pt0=coords+3*begin[0];
8359   const double *pt1=coords+3*begin[nbOfNodes];
8360   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8361   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8362 }
8363
8364 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8365 {
8366   std::size_t sz=std::distance(begin,end);
8367   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8368   std::size_t nbOfNodes(sz/2);
8369   std::copy(begin,end,(int *)tmp);
8370   for(std::size_t j=1;j<nbOfNodes;j++)
8371     {
8372       begin[j]=tmp[nbOfNodes-j];
8373       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8374     }
8375 }
8376
8377 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8378 {
8379   std::size_t sz=std::distance(begin,end);
8380   if(sz!=4)
8381     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8382   double vec0[3],vec1[3];
8383   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8384   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]; 
8385   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;
8386 }
8387
8388 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8389 {
8390   std::size_t sz=std::distance(begin,end);
8391   if(sz!=5)
8392     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8393   double vec0[3];
8394   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8395   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8396   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8397 }
8398
8399 /*!
8400  * 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 ) 
8401  * 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
8402  * a 2D space.
8403  *
8404  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8405  * \param [in] coords the coordinates with nb of components exactly equal to 3
8406  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8407  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8408  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8409  */
8410 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8411 {
8412   int nbFaces=std::count(begin+1,end,-1)+1;
8413   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8414   double *vPtr=v->getPointer();
8415   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8416   double *pPtr=p->getPointer();
8417   const int *stFaceConn=begin+1;
8418   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8419     {
8420       const int *endFaceConn=std::find(stFaceConn,end,-1);
8421       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8422       stFaceConn=endFaceConn+1;
8423     }
8424   pPtr=p->getPointer(); vPtr=v->getPointer();
8425   DataArrayInt *comm1=0,*commI1=0;
8426   v->findCommonTuples(eps,-1,comm1,commI1);
8427   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8428   const int *comm1Ptr=comm1->getConstPointer();
8429   const int *commI1Ptr=commI1->getConstPointer();
8430   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8431   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8432   //
8433   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8434   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8435   mm->finishInsertingCells();
8436   //
8437   for(int i=0;i<nbOfGrps1;i++)
8438     {
8439       int vecId=comm1Ptr[commI1Ptr[i]];
8440       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8441       DataArrayInt *comm2=0,*commI2=0;
8442       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8443       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8444       const int *comm2Ptr=comm2->getConstPointer();
8445       const int *commI2Ptr=commI2->getConstPointer();
8446       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8447       for(int j=0;j<nbOfGrps2;j++)
8448         {
8449           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8450             {
8451               res->insertAtTheEnd(begin,end);
8452               res->pushBackSilent(-1);
8453             }
8454           else
8455             {
8456               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8457               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8458               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8459               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8460               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8461               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8462               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8463               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8464               const int *idsNodePtr=idsNode->getConstPointer();
8465               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];
8466               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8467               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8468               if(std::abs(norm)>eps)
8469                 {
8470                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8471                   mm3->rotate(center,vec,angle);
8472                 }
8473               mm3->changeSpaceDimension(2);
8474               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8475               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8476               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8477               int nbOfCells=mm4->getNumberOfCells();
8478               for(int k=0;k<nbOfCells;k++)
8479                 {
8480                   int l=0;
8481                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8482                     res->pushBackSilent(idsNodePtr[*work]);
8483                   res->pushBackSilent(-1);
8484                 }
8485             }
8486         }
8487     }
8488   res->popBackSilent();
8489 }
8490
8491 /*!
8492  * 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
8493  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8494  * 
8495  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8496  * \param [in] coords coordinates expected to have 3 components.
8497  * \param [in] begin start of the nodal connectivity of the face.
8498  * \param [in] end end of the nodal connectivity (excluded) of the face.
8499  * \param [out] v the normalized vector of size 3
8500  * \param [out] p the pos of plane
8501  */
8502 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8503 {
8504   std::size_t nbPoints=std::distance(begin,end);
8505   if(nbPoints<3)
8506     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8507   double vec[3]={0.,0.,0.};
8508   std::size_t j=0;
8509   bool refFound=false;
8510   for(;j<nbPoints-1 && !refFound;j++)
8511     {
8512       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8513       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8514       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8515       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8516       if(norm>eps)
8517         {
8518           refFound=true;
8519           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8520         }
8521     }
8522   for(std::size_t i=j;i<nbPoints-1;i++)
8523     {
8524       double curVec[3];
8525       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8526       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8527       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8528       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8529       if(norm<eps)
8530         continue;
8531       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8532       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];
8533       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8534       if(norm>eps)
8535         {
8536           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8537           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8538           return ;
8539         }
8540     }
8541   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8542 }
8543
8544 /*!
8545  * This method tries to obtain a well oriented polyhedron.
8546  * If the algorithm fails, an exception will be thrown.
8547  */
8548 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8549 {
8550   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8551   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8552   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8553   isPerm[0]=true;
8554   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8555   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8556   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8557   //
8558   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8559     {
8560       bgFace=begin;
8561       std::size_t smthChanged=0;
8562       for(std::size_t i=0;i<nbOfFaces;i++)
8563         {
8564           endFace=std::find(bgFace+1,end,-1);
8565           nbOfEdgesInFace=std::distance(bgFace,endFace);
8566           if(!isPerm[i])
8567             {
8568               bool b;
8569               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8570                 {
8571                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8572                   std::pair<int,int> p2(p1.second,p1.first);
8573                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8574                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8575                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8576                 }
8577               if(isPerm[i])
8578                 { 
8579                   if(!b)
8580                     std::reverse(bgFace+1,endFace);
8581                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8582                     {
8583                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8584                       std::pair<int,int> p2(p1.second,p1.first);
8585                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8586                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8587                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8588                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8589                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8590                       if(it!=edgesOK.end())
8591                         {
8592                           edgesOK.erase(it);
8593                           edgesFinished.push_back(p1);
8594                         }
8595                       else
8596                         edgesOK.push_back(p1);
8597                     }
8598                 }
8599             }
8600           bgFace=endFace+1;
8601         }
8602       if(smthChanged==0)
8603         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8604     }
8605   if(!edgesOK.empty())
8606     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8607   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8608     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8609       bgFace=begin;
8610       for(std::size_t i=0;i<nbOfFaces;i++)
8611         {
8612           endFace=std::find(bgFace+1,end,-1);
8613           std::reverse(bgFace+1,endFace);
8614           bgFace=endFace+1;
8615         }
8616     }
8617 }
8618
8619 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8620 {
8621   int nbOfNodesExpected(skin->getNumberOfNodes());
8622   const int *n2oPtr(n2o->getConstPointer());
8623   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8624   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8625   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8626   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8627   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8628   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8629   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8630   if(nbOfNodesExpected<1)
8631     return ret.retn();
8632   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8633   *work++=n2oPtr[prevNode];
8634   for(int i=1;i<nbOfNodesExpected;i++)
8635     {
8636       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8637         {
8638           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8639           conn.erase(prevNode);
8640           if(conn.size()==1)
8641             {
8642               int curNode(*(conn.begin()));
8643               *work++=n2oPtr[curNode];
8644               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8645               shar.erase(prevCell);
8646               if(shar.size()==1)
8647                 {
8648                   prevCell=*(shar.begin());
8649                   prevNode=curNode;
8650                 }
8651               else
8652                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8653             }
8654           else
8655             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8656         }
8657       else
8658         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8659     }
8660   return ret.retn();
8661 }
8662
8663 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8664 {
8665   int nbOfNodesExpected(skin->getNumberOfNodes());
8666   int nbOfTurn(nbOfNodesExpected/2);
8667   const int *n2oPtr(n2o->getConstPointer());
8668   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8669   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8670   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8671   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8672   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8673   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8674   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8675   if(nbOfNodesExpected<1)
8676     return ret.retn();
8677   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8678   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8679   for(int i=1;i<nbOfTurn;i++)
8680     {
8681       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8682         {
8683           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8684           conn.erase(prevNode);
8685           if(conn.size()==1)
8686             {
8687               int curNode(*(conn.begin()));
8688               *work=n2oPtr[curNode];
8689               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8690               shar.erase(prevCell);
8691               if(shar.size()==1)
8692                 {
8693                   int curCell(*(shar.begin()));
8694                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8695                   prevCell=curCell;
8696                   prevNode=curNode;
8697                   work++;
8698                 }
8699               else
8700                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8701             }
8702           else
8703             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8704         }
8705       else
8706         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8707     }
8708   return ret.retn();
8709 }
8710
8711 /*!
8712  * This method makes the assumption spacedimension == meshdimension == 2.
8713  * This method works only for linear cells.
8714  * 
8715  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8716  */
8717 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8718 {
8719   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8720     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8721   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8722   int oldNbOfNodes(skin->getNumberOfNodes());
8723   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8724   int nbOfNodesExpected(skin->getNumberOfNodes());
8725   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8726   int nbCells(skin->getNumberOfCells());
8727   if(nbCells==nbOfNodesExpected)
8728     return buildUnionOf2DMeshLinear(skin,n2o);
8729   else if(2*nbCells==nbOfNodesExpected)
8730     return buildUnionOf2DMeshQuadratic(skin,n2o);
8731   else
8732     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8733 }
8734
8735 /*!
8736  * This method makes the assumption spacedimension == meshdimension == 3.
8737  * This method works only for linear cells.
8738  * 
8739  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8740  */
8741 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8742 {
8743   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8744     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8745   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8746   const int *conn=m->getNodalConnectivity()->getConstPointer();
8747   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8748   int nbOfCells=m->getNumberOfCells();
8749   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8750   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8751   if(nbOfCells<1)
8752     return ret.retn();
8753   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8754   for(int i=1;i<nbOfCells;i++)
8755     {
8756       *work++=-1;
8757       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8758     }
8759   return ret.retn();
8760 }
8761
8762 /*!
8763  * \brief Creates a graph of cell neighbors
8764  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8765  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8766  *  For example
8767  *  - index:  0 3 5 6 6
8768  *  - value:  1 2 3 2 3 3
8769  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8770  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8771  */
8772 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8773 {
8774   checkConnectivityFullyDefined();
8775
8776   int meshDim = this->getMeshDimension();
8777   ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8778   ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8779   this->getReverseNodalConnectivity(revConn,indexr);
8780   const int* indexr_ptr=indexr->getConstPointer();
8781   const int* revConn_ptr=revConn->getConstPointer();
8782
8783   const ParaMEDMEM::DataArrayInt* index;
8784   const ParaMEDMEM::DataArrayInt* conn;
8785   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8786   index=this->getNodalConnectivityIndex();
8787   int nbCells=this->getNumberOfCells();
8788   const int* index_ptr=index->getConstPointer();
8789   const int* conn_ptr=conn->getConstPointer();
8790
8791   //creating graph arcs (cell to cell relations)
8792   //arcs are stored in terms of (index,value) notation
8793   // 0 3 5 6 6
8794   // 1 2 3 2 3 3
8795   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8796   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8797
8798   //warning here one node have less than or equal effective number of cell with it
8799   //but cell could have more than effective nodes
8800   //because other equals nodes in other domain (with other global inode)
8801   std::vector <int> cell2cell_index(nbCells+1,0);
8802   std::vector <int> cell2cell;
8803   cell2cell.reserve(3*nbCells);
8804
8805   for (int icell=0; icell<nbCells;icell++)
8806     {
8807       std::map<int,int > counter;
8808       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8809         {
8810           int inode=conn_ptr[iconn];
8811           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8812             {
8813               int icell2=revConn_ptr[iconnr];
8814               std::map<int,int>::iterator iter=counter.find(icell2);
8815               if (iter!=counter.end()) (iter->second)++;
8816               else counter.insert(std::make_pair(icell2,1));
8817             }
8818         }
8819       for (std::map<int,int>::const_iterator iter=counter.begin();
8820            iter!=counter.end(); iter++)
8821         if (iter->second >= meshDim)
8822           {
8823             cell2cell_index[icell+1]++;
8824             cell2cell.push_back(iter->first);
8825           }
8826     }
8827   indexr->decrRef();
8828   revConn->decrRef();
8829   cell2cell_index[0]=0;
8830   for (int icell=0; icell<nbCells;icell++)
8831     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8832
8833   //filling up index and value to create skylinearray structure
8834   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8835   return array;
8836 }
8837
8838 /*!
8839  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8840  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8841  */
8842 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8843 {
8844   double *w=zipFrmt;
8845   if(spaceDim==3)
8846     for(int i=0;i<nbOfNodesInCell;i++)
8847       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8848   else if(spaceDim==2)
8849     {
8850       for(int i=0;i<nbOfNodesInCell;i++)
8851         {
8852           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8853           *w++=0.;
8854         }
8855     }
8856   else
8857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8858 }
8859
8860 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8861 {
8862   int nbOfCells=getNumberOfCells();
8863   if(nbOfCells<=0)
8864     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8865   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};
8866   ofs << "  <" << getVTKDataSetType() << ">\n";
8867   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8868   ofs << "      <PointData>\n" << pointData << std::endl;
8869   ofs << "      </PointData>\n";
8870   ofs << "      <CellData>\n" << cellData << std::endl;
8871   ofs << "      </CellData>\n";
8872   ofs << "      <Points>\n";
8873   if(getSpaceDimension()==3)
8874     _coords->writeVTK(ofs,8,"Points",byteData);
8875   else
8876     {
8877       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8878       coo->writeVTK(ofs,8,"Points",byteData);
8879     }
8880   ofs << "      </Points>\n";
8881   ofs << "      <Cells>\n";
8882   const int *cPtr=_nodal_connec->getConstPointer();
8883   const int *cIPtr=_nodal_connec_index->getConstPointer();
8884   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8885   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8886   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8888   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8889   int szFaceOffsets=0,szConn=0;
8890   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8891     {
8892       *w2=cPtr[cIPtr[i]];
8893       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8894         {
8895           *w1=-1;
8896           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8897           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8898         }
8899       else
8900         {
8901           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8902           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8903           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8904           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8905           w4=std::copy(c.begin(),c.end(),w4);
8906         }
8907     }
8908   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8909   types->writeVTK(ofs,8,"UInt8","types",byteData);
8910   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8911   if(szFaceOffsets!=0)
8912     {//presence of Polyhedra
8913       connectivity->reAlloc(szConn);
8914       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8915       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8916       w1=faces->getPointer();
8917       for(int i=0;i<nbOfCells;i++)
8918         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8919           {
8920             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8921             *w1++=nbFaces;
8922             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8923             for(int j=0;j<nbFaces;j++)
8924               {
8925                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8926                 *w1++=(int)std::distance(w6,w5);
8927                 w1=std::copy(w6,w5,w1);
8928                 w6=w5+1;
8929               }
8930           }
8931       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8932     }
8933   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8934   ofs << "      </Cells>\n";
8935   ofs << "    </Piece>\n";
8936   ofs << "  </" << getVTKDataSetType() << ">\n";
8937 }
8938
8939 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8940 {
8941   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8942   if(_mesh_dim==-2)
8943     { stream << " Not set !"; return ; }
8944   stream << " Mesh dimension : " << _mesh_dim << ".";
8945   if(_mesh_dim==-1)
8946     return ;
8947   if(!_coords)
8948     { stream << " No coordinates set !"; return ; }
8949   if(!_coords->isAllocated())
8950     { stream << " Coordinates set but not allocated !"; return ; }
8951   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8952   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8953   if(!_nodal_connec_index)
8954     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8955   if(!_nodal_connec_index->isAllocated())
8956     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8957   int lgth=_nodal_connec_index->getNumberOfTuples();
8958   int cpt=_nodal_connec_index->getNumberOfComponents();
8959   if(cpt!=1 || lgth<1)
8960     return ;
8961   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8962 }
8963
8964 std::string MEDCouplingUMesh::getVTKDataSetType() const
8965 {
8966   return std::string("UnstructuredGrid");
8967 }
8968
8969 std::string MEDCouplingUMesh::getVTKFileExtension() const
8970 {
8971   return std::string("vtu");
8972 }
8973
8974 /*!
8975  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8976  * returns a result mesh constituted by polygons.
8977  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8978  * all nodes from m2.
8979  * The meshes should be in 2D space. In
8980  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8981  * meshes.
8982  *  \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
8983  *                      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)
8984  *  \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
8985  *                      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)
8986  *  \param [in] eps - precision used to detect coincident mesh entities.
8987  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8988  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8989  *         this array using decrRef() as it is no more needed.
8990  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8991  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8992  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8993  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8994  *         it is no more needed.  
8995  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8996  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8997  *         is no more needed.  
8998  *  \throw If the coordinates array is not set in any of the meshes.
8999  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
9000  *  \throw If any of the meshes is not a 2D mesh in 2D space.
9001  *
9002  *  \sa conformize2D, mergeNodes
9003  */
9004 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9005                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9006 {
9007   if(!m1 || !m2)
9008     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9009   m1->checkFullyDefined();
9010   m2->checkFullyDefined();
9011   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9012     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
9013
9014   // Step 1: compute all edge intersections (new nodes)
9015   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9016   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9017   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9018   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9019   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9020                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9021                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9022   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9023   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9024   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9025
9026   // Step 2: re-order newly created nodes according to the ordering found in m2
9027   std::vector< std::vector<int> > intersectEdge2;
9028   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9029   subDiv2.clear(); dd5=0; dd6=0;
9030
9031   // Step 3:
9032   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9033   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9034   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9035                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9036
9037   // Step 4: Prepare final result:
9038   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9039   addCooDa->alloc((int)(addCoo.size())/2,2);
9040   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9041   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9042   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9043   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9044   std::vector<const DataArrayDouble *> coordss(4);
9045   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9046   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9047   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9048   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9049   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9050   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9051   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9052   ret->setConnectivity(conn,connI,true);
9053   ret->setCoords(coo);
9054   cellNb1=c1.retn(); cellNb2=c2.retn();
9055   return ret.retn();
9056 }
9057
9058 /// @cond INTERNAL
9059
9060 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9061 {
9062   if(candidates.empty())
9063     return false;
9064   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9065     {
9066       const std::vector<int>& pool(intersectEdge1[*it]);
9067       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9068       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9069         {
9070           retVal=*it+1;
9071           return true;
9072         }
9073       tmp[0]=stop; tmp[1]=start;
9074       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9075         {
9076           retVal=-*it-1;
9077           return true;
9078         }
9079     }
9080   return false;
9081 }
9082
9083 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,
9084                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9085 {
9086   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9087   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9088   int nCells(mesh1D->getNumberOfCells());
9089   if(nCells!=(int)intersectEdge2.size())
9090     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9091   const DataArrayDouble *coo2(mesh1D->getCoords());
9092   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9093   const double *coo2Ptr(coo2->begin());
9094   int offset1(coords1->getNumberOfTuples());
9095   int offset2(offset1+coo2->getNumberOfTuples());
9096   int offset3(offset2+addCoo.size()/2);
9097   std::vector<double> addCooQuad;
9098   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9099   int tmp[4],cicnt(0),kk(0);
9100   for(int i=0;i<nCells;i++)
9101     {
9102       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9103       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9104       const std::vector<int>& subEdges(intersectEdge2[i]);
9105       int nbSubEdge(subEdges.size()/2);
9106       for(int j=0;j<nbSubEdge;j++,kk++)
9107         {
9108           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));
9109           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9110           INTERP_KERNEL::Edge *e2Ptr(e2);
9111           std::map<int,int>::const_iterator itm;
9112           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9113             {
9114               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9115               itm=mergedNodes.find(subEdges[2*j]);
9116               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9117               itm=mergedNodes.find(subEdges[2*j+1]);
9118               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9119               tmp[3]=offset3+(int)addCooQuad.size()/2;
9120               double tmp2[2];
9121               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9122               cicnt+=4;
9123               cOut->insertAtTheEnd(tmp,tmp+4);
9124               ciOut->pushBackSilent(cicnt);
9125             }
9126           else
9127             {
9128               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9129               itm=mergedNodes.find(subEdges[2*j]);
9130               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9131               itm=mergedNodes.find(subEdges[2*j+1]);
9132               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9133               cicnt+=3;
9134               cOut->insertAtTheEnd(tmp,tmp+3);
9135               ciOut->pushBackSilent(cicnt);
9136             }
9137           int tmp00;
9138           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9139             {
9140               idsInRetColinear->pushBackSilent(kk);
9141               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9142             }
9143         }
9144       e->decrRef();
9145     }
9146   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9147   ret->setConnectivity(cOut,ciOut,true);
9148   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9149   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9150   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9151   std::vector<const DataArrayDouble *> coordss(4);
9152   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9153   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9154   ret->setCoords(arr);
9155   return ret.retn();
9156 }
9157
9158 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9159 {
9160   std::vector<int> allEdges;
9161   for(const int *it2(descBg);it2!=descEnd;it2++)
9162     {
9163       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9164       if(*it2>0)
9165         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9166       else
9167         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9168     }
9169   std::size_t nb(allEdges.size());
9170   if(nb%2!=0)
9171     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9172   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9173   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9174   ret->setCoords(coords);
9175   ret->allocateCells(1);
9176   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9177   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9178     connOut[kk]=allEdges[2*kk];
9179   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9180   return ret.retn();
9181 }
9182
9183 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9184 {
9185   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9186   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9187   std::size_t ii(0);
9188   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9189   if(sz!=std::distance(descBg,descEnd))
9190     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9191   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9192   std::vector<int> allEdges,centers;
9193   const double *coordsPtr(coords->begin());
9194   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9195   int offset(coords->getNumberOfTuples());
9196   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9197     {
9198       INTERP_KERNEL::NormalizedCellType typeOfSon;
9199       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9200       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9201       if(*it2>0)
9202         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9203       else
9204         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9205       if(edge1.size()==2)
9206         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9207       else
9208         {//the current edge has been subsplit -> create corresponding centers.
9209           std::size_t nbOfCentersToAppend(edge1.size()/2);
9210           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9211           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9212           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9213           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9214             {
9215               double tmpp[2];
9216               const double *aa(coordsPtr+2*(*it3++));
9217               const double *bb(coordsPtr+2*(*it3++));
9218               ee->getMiddleOfPoints(aa,bb,tmpp);
9219               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9220               centers.push_back(offset+k);
9221             }
9222         }
9223     }
9224   std::size_t nb(allEdges.size());
9225   if(nb%2!=0)
9226     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9227   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9228   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9229   if(addCoo->empty())
9230     ret->setCoords(coords);
9231   else
9232     {
9233       addCoo->rearrange(2);
9234       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9235       ret->setCoords(addCoo);
9236     }
9237   ret->allocateCells(1);
9238   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9239   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9240     connOut[kk]=allEdges[2*kk];
9241   connOut.insert(connOut.end(),centers.begin(),centers.end());
9242   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9243   return ret.retn();
9244 }
9245
9246 /*!
9247  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9248  * of those edges.
9249  *
9250  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9251  */
9252 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9253 {
9254   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9255   if(!cm.isQuadratic())
9256     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9257   else
9258     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9259 }
9260
9261 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9262 {
9263   bool isQuad(false);
9264   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9265     {
9266       const INTERP_KERNEL::Edge *ee(*it);
9267       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9268         isQuad=true;
9269     }
9270   if(!isQuad)
9271     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9272   else
9273     {
9274       const double *coo(mesh2D->getCoords()->begin());
9275       std::size_t sz(conn.size());
9276       std::vector<double> addCoo;
9277       std::vector<int> conn2(conn);
9278       int offset(mesh2D->getNumberOfNodes());
9279       for(std::size_t i=0;i<sz;i++)
9280         {
9281           double tmp[2];
9282           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9283           addCoo.insert(addCoo.end(),tmp,tmp+2);
9284           conn2.push_back(offset+(int)i);
9285         }
9286       mesh2D->getCoords()->rearrange(1);
9287       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9288       mesh2D->getCoords()->rearrange(2);
9289       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9290     }
9291 }
9292
9293 /*!
9294  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9295  *
9296  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9297  * a set of edges defined in \a splitMesh1D.
9298  */
9299 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9300                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9301 {
9302   std::size_t nb(edge1Bis.size()/2);
9303   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9304   int iEnd(splitMesh1D->getNumberOfCells());
9305   if(iEnd==0)
9306     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9307   std::size_t ii,jj;
9308   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9309   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9310   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9311   //
9312   if(jj==nb)
9313     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9314       out0.resize(1); out1.resize(1);
9315       std::vector<int>& connOut(out0[0]);
9316       connOut.resize(nbOfEdgesOf2DCellSplit);
9317       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9318       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9319       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9320         {
9321           connOut[kk]=edge1Bis[2*kk];
9322           edgesPtr[kk]=edge1BisPtr[2*kk];
9323         }
9324     }
9325   else
9326     {
9327       // [i,iEnd[ contains the
9328       out0.resize(2); out1.resize(2);
9329       std::vector<int>& connOutLeft(out0[0]);
9330       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9331       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9332       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9333       for(std::size_t k=ii;k<jj+1;k++)
9334         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9335       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9336       for(int ik=0;ik<iEnd;ik++)
9337         {
9338           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9339           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9340           ees[ik]=ee;
9341         }
9342       for(int ik=iEnd-1;ik>=0;ik--)
9343         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9344       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9345         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9346       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9347       for(int ik=0;ik<iEnd;ik++)
9348         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9349       eright.insert(eright.end(),ees.begin(),ees.end());
9350     }
9351 }
9352
9353 /// @endcond
9354
9355 /// @cond INTERNAL
9356
9357 struct CellInfo
9358 {
9359 public:
9360   CellInfo() { }
9361   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9362 public:
9363   std::vector<int> _edges;
9364   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9365 };
9366
9367 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9368 {
9369   std::size_t nbe(edges.size());
9370   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9371   for(std::size_t i=0;i<nbe;i++)
9372     {
9373       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9374       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9375     }
9376   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9377   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9378   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9379 }
9380
9381 class EdgeInfo
9382 {
9383 public:
9384   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9385   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9386   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9387   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9388   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9389 private:
9390   int _istart;
9391   int _iend;
9392   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9393   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9394   int _left;
9395   int _right;
9396 };
9397
9398 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9399 {
9400   const MEDCouplingUMesh *mesh(_mesh);
9401   if(mesh)
9402     return ;
9403   if(_right<pos)
9404     return ;
9405   if(_left>pos)
9406     { _left++; _right++; return ; }
9407   if(_right==pos)
9408     {
9409       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9410       if((isLeft && isRight) || (!isLeft && !isRight))
9411         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9412       if(isLeft)
9413         return ;
9414       if(isRight)
9415         {
9416           _right++;
9417           return ;
9418         }
9419     }
9420   if(_left==pos)
9421     {
9422       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9423       if((isLeft && isRight) || (!isLeft && !isRight))
9424         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9425       if(isLeft)
9426         {
9427           _right++;
9428           return ;
9429         }
9430       if(isRight)
9431         {
9432           _left++;
9433           _right++;
9434           return ;
9435         }
9436     }
9437 }
9438
9439 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9440 {
9441   const MEDCouplingUMesh *mesh(_mesh);
9442   if(!mesh)
9443     {
9444       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9445     }
9446   else
9447     {// not fully splitting cell case
9448       if(mesh2D->getNumberOfCells()==1)
9449         {//little optimization. 1 cell no need to find in which cell mesh is !
9450           neighbors[0]=offset; neighbors[1]=offset;
9451           return;
9452         }
9453       else
9454         {
9455           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9456           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9457           if(cellId==-1)
9458             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9459           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9460         }
9461     }
9462 }
9463
9464 class VectorOfCellInfo
9465 {
9466 public:
9467   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9468   std::size_t size() const { return _pool.size(); }
9469   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9470   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);
9471   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9472   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9473   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9474   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9475 private:
9476   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9477   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9478   const CellInfo& get(int pos) const;
9479   CellInfo& get(int pos);
9480 private:
9481   std::vector<CellInfo> _pool;
9482   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9483   std::vector<EdgeInfo> _edge_info;
9484 };
9485
9486 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9487 {
9488   _pool[0]._edges=edges;
9489   _pool[0]._edges_ptr=edgesPtr;
9490 }
9491
9492 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9493 {
9494   if(_pool.empty())
9495     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9496   if(_pool.size()==1)
9497     return 0;
9498   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9499   if(!zeMesh)
9500     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9501   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9502   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9503 }
9504
9505 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)
9506 {
9507   get(pos);//to check pos
9508   bool isFast(pos==0 && _pool.size()==1);
9509   std::size_t sz(edges.size());
9510   // dealing with edges
9511   if(sz==1)
9512     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9513   else
9514     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9515   //
9516   std::vector<CellInfo> pool(_pool.size()-1+sz);
9517   for(int i=0;i<pos;i++)
9518     pool[i]=_pool[i];
9519   for(std::size_t j=0;j<sz;j++)
9520     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9521   for(int i=pos+1;i<(int)_pool.size();i++)
9522     pool[i+sz-1]=_pool[i];
9523   _pool=pool;
9524   //
9525   if(sz==2)
9526     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9527   //
9528   if(isFast)
9529     {
9530       _ze_mesh=mesh;
9531       return ;
9532     }
9533   //
9534   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9535   if(pos>0)
9536     {
9537       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9538       ms.push_back(elt);
9539     }
9540   ms.push_back(mesh);
9541   if(pos<_ze_mesh->getNumberOfCells()-1)
9542   {
9543     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9544     ms.push_back(elt);
9545   }
9546   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9547   for(std::size_t j=0;j<ms2.size();j++)
9548     ms2[j]=ms[j];
9549   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9550 }
9551
9552 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9553 {
9554   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9555 }
9556
9557 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9558 {
9559   if(pos<0)
9560     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9561   int ret(0);
9562   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9563     {
9564       if((*it).isInMyRange(pos))
9565         return ret;
9566     }
9567   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9568 }
9569
9570 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9571 {
9572   get(pos);//to check;
9573   if(_edge_info.empty())
9574     return ;
9575   std::size_t sz(_edge_info.size()-1);
9576   for(std::size_t i=0;i<sz;i++)
9577     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9578 }
9579
9580 const CellInfo& VectorOfCellInfo::get(int pos) const
9581 {
9582   if(pos<0 || pos>=(int)_pool.size())
9583     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9584   return _pool[pos];
9585 }
9586
9587 CellInfo& VectorOfCellInfo::get(int pos)
9588 {
9589   if(pos<0 || pos>=(int)_pool.size())
9590     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9591   return _pool[pos];
9592 }
9593
9594 /*!
9595  * Given :
9596  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9597  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9598  *
9599  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9600  *
9601  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9602  *
9603  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9604  */
9605 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9606                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9607 {
9608   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9609   if(nbCellsInSplitMesh1D==0)
9610     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9611   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9612   std::size_t nb(allEdges.size()),jj;
9613   if(nb%2!=0)
9614     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9615   std::vector<int> edge1Bis(nb*2);
9616   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9617   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9618   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9619   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9620   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9621   //
9622   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9623   int *idsLeftRightPtr(idsLeftRight->getPointer());
9624   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9625   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9626     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9627       int iEnd(iStart);
9628       for(;iEnd<nbCellsInSplitMesh1D;)
9629         {
9630           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9631           if(jj!=nb)
9632             break;
9633           else
9634             iEnd++;
9635         }
9636       if(iEnd<nbCellsInSplitMesh1D)
9637         iEnd++;
9638       //
9639       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9640       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9641       //
9642       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9643       retTmp->setCoords(splitMesh1D->getCoords());
9644       retTmp->allocateCells();
9645
9646       std::vector< std::vector<int> > out0;
9647       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9648
9649       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9650       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9651         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9652       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9653       //
9654       iStart=iEnd;
9655     }
9656   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9657     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9658   return pool.getZeMesh().retn();
9659 }
9660
9661 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9662                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9663                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9664 {
9665   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9666   //
9667   std::vector<int> allEdges;
9668   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9669   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9670     {
9671       int edgeId(std::abs(*it)-1);
9672       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9673       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9674       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9675       if(*it>0)
9676         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9677       else
9678         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9679       std::size_t sz(edge1.size());
9680       for(std::size_t cnt=0;cnt<sz;cnt++)
9681         allEdgesPtr.push_back(ee);
9682     }
9683   //
9684   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9685 }
9686
9687 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9688 {
9689   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9690     {//easy case comparison not
9691       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9692     }
9693   else if(typ1.isQuadratic() && typ2.isQuadratic())
9694     {
9695       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9696       if(!status0)
9697         return false;
9698       if(conn1[2]==conn2[2])
9699         return true;
9700       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9701       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9702       return dist<eps;
9703     }
9704   else
9705     {//only one is quadratic
9706       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9707       if(!status0)
9708         return false;
9709       const double *a(0),*bb(0),*be(0);
9710       if(typ1.isQuadratic())
9711         {
9712           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9713         }
9714       else
9715         {
9716           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9717         }
9718       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9719       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9720       return dist<eps;
9721     }
9722 }
9723
9724 /*!
9725  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9726  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9727  *
9728  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9729  */
9730 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9731 {
9732   if(candidatesIn2DEnd==candidatesIn2DBg)
9733     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9734   const double *coo(mesh2DSplit->getCoords()->begin());
9735   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9736     return *candidatesIn2DBg;
9737   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9738   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9739   if(cellIdInMesh1DSplitRelative<0)
9740     cur1D->changeOrientationOfCells();
9741   const int *c1D(cur1D->getNodalConnectivity()->begin());
9742   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9743   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9744     {
9745       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9746       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9747       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9748       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9749       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9750       for(unsigned it2=0;it2<sz;it2++)
9751         {
9752           INTERP_KERNEL::NormalizedCellType typeOfSon;
9753           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9754           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9755           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9756             return *it;
9757         }
9758     }
9759   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9760 }
9761
9762 /// @endcond
9763
9764 /*!
9765  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9766  * 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
9767  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9768  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9769  *
9770  * \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
9771  *                      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)
9772  * \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
9773  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9774  * \param [in] eps - precision used to perform intersections and localization operations.
9775  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9776  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9777  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9778  *                               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.
9779  * \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
9780  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9781  *                               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.
9782  *
9783  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9784  */
9785 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9786 {
9787   if(!mesh2D || !mesh1D)
9788     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9789   mesh2D->checkFullyDefined();
9790   mesh1D->checkFullyDefined();
9791   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9792   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9793     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9794   // Step 1: compute all edge intersections (new nodes)
9795   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9796   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9797   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9798   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9799   //
9800   // Build desc connectivity
9801   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9802   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9803   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9804   std::map<int,int> mergedNodes;
9805   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9806   // use mergeNodes to fix intersectEdge1
9807   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9808     {
9809       std::size_t n((*it0).size()/2);
9810       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9811       std::map<int,int>::const_iterator it1;
9812       it1=mergedNodes.find(eltStart);
9813       if(it1!=mergedNodes.end())
9814         (*it0)[0]=(*it1).second;
9815       it1=mergedNodes.find(eltEnd);
9816       if(it1!=mergedNodes.end())
9817         (*it0)[2*n-1]=(*it1).second;
9818     }
9819   //
9820   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9821   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9822   // Step 2: re-order newly created nodes according to the ordering found in m2
9823   std::vector< std::vector<int> > intersectEdge2;
9824   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9825   subDiv2.clear();
9826   // Step 3: compute splitMesh1D
9827   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9828   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9829   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9830       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9831   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9832   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9833   // deal with cells in mesh2D that are not cut but only some of their edges are
9834   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9835   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9836   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9837   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
9838   if(!idsInDesc2DToBeRefined->empty())
9839     {
9840       DataArrayInt *out0(0),*outi0(0);
9841       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9842       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9843       out0s=out0;
9844       out0s=out0s->buildUnique();
9845       out0s->sort(true);
9846     }
9847   //
9848   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9849   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9850   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9851   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9852   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9853   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9854   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9855     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9856   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9857   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9858   if((DataArrayInt *)out0s)
9859     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9860   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9861   // OK all is ready to insert in ret2 mesh
9862   if(!untouchedCells->empty())
9863     {// the most easy part, cells in mesh2D not impacted at all
9864       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9865       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9866       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9867     }
9868   if((DataArrayInt *)out0s)
9869     {// here dealing with cells in out0s but not in cellsToBeModified
9870       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9871       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9872       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9873         {
9874           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9875           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9876         }
9877       int offset(ret2->getNumberOfTuples());
9878       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9879       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9880       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9881       int kk(0),*ret3ptr(partOfRet3->getPointer());
9882       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9883         {
9884           int faceId(std::abs(*it)-1);
9885           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9886             {
9887               int tmp(fewModifiedCells->locateValue(*it2));
9888               if(tmp!=-1)
9889                 {
9890                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9891                     ret3ptr[2*kk]=tmp+offset;
9892                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9893                     ret3ptr[2*kk+1]=tmp+offset;
9894                 }
9895               else
9896                 {//the current edge is shared by a 2D cell that will be split just after
9897                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9898                     ret3ptr[2*kk]=-(*it2+1);
9899                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9900                     ret3ptr[2*kk+1]=-(*it2+1);
9901                 }
9902             }
9903         }
9904       m1Desc->setCoords(ret1->getCoords());
9905       ret1NonCol->setCoords(ret1->getCoords());
9906       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9907       if(!outMesh2DSplit.empty())
9908         {
9909           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9910           for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9911             (*itt)->setCoords(da);
9912         }
9913     }
9914   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9915   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9916     {
9917       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9918       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9919       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9920       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9921       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9922       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));
9923       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9924       outMesh2DSplit.push_back(splitOfOneCell);
9925       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9926         ret2->pushBackSilent(*it);
9927     }
9928   //
9929   std::size_t nbOfMeshes(outMesh2DSplit.size());
9930   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9931   for(std::size_t i=0;i<nbOfMeshes;i++)
9932     tmp[i]=outMesh2DSplit[i];
9933   //
9934   ret1->getCoords()->setInfoOnComponents(compNames);
9935   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9936   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9937   ret3->rearrange(1);
9938   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9939   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9940     {
9941       int old2DCellId(-ret3->getIJ(*it,0)-1);
9942       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9943       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
9944     }
9945   ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9946   ret3->rearrange(2);
9947   //
9948   splitMesh1D=ret1.retn();
9949   splitMesh2D=ret2D.retn();
9950   cellIdInMesh2D=ret2.retn();
9951   cellIdInMesh1D=ret3.retn();
9952 }
9953
9954 /**
9955  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9956  * (newly created) nodes corresponding to the edge intersections.
9957  * Output params:
9958  * @param[out] cr, crI connectivity of the resulting mesh
9959  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9960  * TODO: describe input parameters
9961  */
9962 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9963                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9964                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9965                                                          const std::vector<double>& addCoords,
9966                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9967 {
9968   static const int SPACEDIM=2;
9969   const double *coo1(m1->getCoords()->getConstPointer());
9970   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9971   int offset1(m1->getNumberOfNodes());
9972   const double *coo2(m2->getCoords()->getConstPointer());
9973   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9974   int offset2(offset1+m2->getNumberOfNodes());
9975   int offset3(offset2+((int)addCoords.size())/2);
9976   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9977   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9978   // Here a BBTree on 2D-cells, not on segments:
9979   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9980   int ncell1(m1->getNumberOfCells());
9981   crI.push_back(0);
9982   for(int i=0;i<ncell1;i++)
9983     {
9984       std::vector<int> candidates2;
9985       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9986       std::map<INTERP_KERNEL::Node *,int> mapp;
9987       std::map<int,INTERP_KERNEL::Node *> mappRev;
9988       INTERP_KERNEL::QuadraticPolygon pol1;
9989       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9990       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9991       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9992       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9993       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9994       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9995           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9996       //
9997       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
9998       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9999       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
10000       for(it1.first();!it1.finished();it1.next())
10001         edges1.insert(it1.current()->getPtr());
10002       //
10003       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
10004       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10005       int ii=0;
10006       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10007         {
10008           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10009           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10010           // Complete mapping with elements coming from the current cell it2 in mesh2:
10011           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10012           // pol2 is the new QP in the final merged result.
10013           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10014               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10015         }
10016       ii=0;
10017       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10018         {
10019           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10020           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10021           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10022           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10023         }
10024       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10025       // by m2 but that we still want to keep in the final result.
10026       if(!edges1.empty())
10027         {
10028           try
10029           {
10030               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10031           }
10032           catch(INTERP_KERNEL::Exception& e)
10033           {
10034               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();
10035               throw INTERP_KERNEL::Exception(oss.str().c_str());
10036           }
10037         }
10038       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10039         (*it).second->decrRef();
10040     }
10041 }
10042
10043 /**
10044  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10045  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10046  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10047  * The caller is to deal with the resulting DataArrayInt.
10048  *  \throw If the coordinate array is not set.
10049  *  \throw If the nodal connectivity of the cells is not defined.
10050  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10051  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10052  *
10053  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10054  */
10055 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10056 {
10057   checkFullyDefined();
10058   if(getMeshDimension()!=1)
10059     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10060
10061   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10062   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10063   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10064   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10065   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10066   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10067   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10068   const int * dsi(_dsi->getConstPointer());
10069   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10070   m_points=0;
10071   if (dsii->getNumberOfTuples())
10072     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10073
10074   int nc(getNumberOfCells());
10075   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10076   result->alloc(nc,1);
10077
10078   // set of edges not used so far
10079   std::set<int> edgeSet;
10080   for (int i=0; i<nc; edgeSet.insert(i), i++);
10081
10082   int startSeg=0;
10083   int newIdx=0;
10084   // while we have points with only one neighbor segments
10085   do
10086     {
10087       std::list<int> linePiece;
10088       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10089       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10090         {
10091           // Fill the list forward (resp. backward) from the start segment:
10092           int activeSeg = startSeg;
10093           int prevPointId = -20;
10094           int ptId;
10095           while (!edgeSet.empty())
10096             {
10097               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10098                 {
10099                   if (direction==0)
10100                     linePiece.push_back(activeSeg);
10101                   else
10102                     linePiece.push_front(activeSeg);
10103                   edgeSet.erase(activeSeg);
10104                 }
10105
10106               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10107               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10108               if (dsi[ptId] == 1) // hitting the end of the line
10109                 break;
10110               prevPointId = ptId;
10111               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10112               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10113             }
10114         }
10115       // Done, save final piece into DA:
10116       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10117       newIdx += linePiece.size();
10118
10119       // identify next valid start segment (one which is not consumed)
10120       if(!edgeSet.empty())
10121         startSeg = *(edgeSet.begin());
10122     }
10123   while (!edgeSet.empty());
10124   return result.retn();
10125 }
10126
10127 /// @cond INTERNAL
10128
10129 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10130 {
10131   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10132   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10133   if(it==m.end())
10134     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10135   int v((*it).second);
10136   if(v==forbVal0 || v==forbVal1)
10137     return ;
10138   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10139     isect.push_back(v);
10140 }
10141
10142 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10143 {
10144   int sz(c.size());
10145   if(sz<=1)
10146     return false;
10147   bool presenceOfOn(false);
10148   for(int i=0;i<sz;i++)
10149     {
10150       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10151       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10152         continue ;
10153       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10154       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10155     }
10156   return presenceOfOn;
10157 }
10158
10159 /// @endcond
10160
10161 /**
10162  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10163  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10164  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10165  * a minimal creation of new nodes is wanted.
10166  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10167  * nodes if a SEG3 is split without information of middle.
10168  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10169  * avoid to have a non conform mesh.
10170  *
10171  * \return int - the number of new nodes created (in most of cases 0).
10172  * 
10173  * \throw If \a this is not coherent.
10174  * \throw If \a this has not spaceDim equal to 2.
10175  * \throw If \a this has not meshDim equal to 2.
10176  * \throw If some subcells needed to be split are orphan.
10177  * \sa MEDCouplingUMesh::conformize2D
10178  */
10179 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10180 {
10181   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10182     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10183   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10184   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10185     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10186   if(midOpt==0 && midOptI==0)
10187     {
10188       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10189       return 0;
10190     }
10191   else if(midOpt!=0 && midOptI!=0)
10192     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10193   else
10194     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10195 }
10196
10197 /*!
10198  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10199  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10200  * 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
10201  * 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).
10202  * 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.
10203  * 
10204  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10205  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10206  *
10207  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10208  * This method expects that all nodes in \a this are not closer than \a eps.
10209  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10210  * 
10211  * \param [in] eps the relative error to detect merged edges.
10212  * \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
10213  *                           that the user is expected to deal with.
10214  *
10215  * \throw If \a this is not coherent.
10216  * \throw If \a this has not spaceDim equal to 2.
10217  * \throw If \a this has not meshDim equal to 2.
10218  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10219  */
10220 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10221 {
10222   static const int SPACEDIM=2;
10223   checkCoherency();
10224   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10225     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10226   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10227   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10228   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10229   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10230   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10231   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10232   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10233   std::vector<double> addCoo;
10234   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10235   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10236   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10237   for(int i=0;i<nDescCell;i++)
10238     {
10239       std::vector<int> candidates;
10240       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10241       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10242         if(*it>i)
10243           {
10244             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10245             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10246                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10247             INTERP_KERNEL::MergePoints merge;
10248             INTERP_KERNEL::QuadraticPolygon c1,c2;
10249             e1->intersectWith(e2,merge,c1,c2);
10250             e1->decrRef(); e2->decrRef();
10251             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10252               overlapEdge[i].push_back(*it);
10253             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10254               overlapEdge[*it].push_back(i);
10255           }
10256     }
10257   // splitting done. sort intersect point in intersectEdge.
10258   std::vector< std::vector<int> > middle(nDescCell);
10259   int nbOf2DCellsToBeSplit(0);
10260   bool middleNeedsToBeUsed(false);
10261   std::vector<bool> cells2DToTreat(nDescCell,false);
10262   for(int i=0;i<nDescCell;i++)
10263     {
10264       std::vector<int>& isect(intersectEdge[i]);
10265       int sz((int)isect.size());
10266       if(sz>1)
10267         {
10268           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10269           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10270           e->sortSubNodesAbs(coords,isect);
10271           e->decrRef();
10272         }
10273       if(sz!=0)
10274         {
10275           int idx0(rdi[i]),idx1(rdi[i+1]);
10276           if(idx1-idx0!=1)
10277             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10278           if(!cells2DToTreat[rd[idx0]])
10279             {
10280               cells2DToTreat[rd[idx0]]=true;
10281               nbOf2DCellsToBeSplit++;
10282             }
10283           // try to reuse at most eventual 'middle' of SEG3
10284           std::vector<int>& mid(middle[i]);
10285           mid.resize(sz+1,-1);
10286           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10287             {
10288               middleNeedsToBeUsed=true;
10289               const std::vector<int>& candidates(overlapEdge[i]);
10290               std::vector<int> trueCandidates;
10291               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10292                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10293                   trueCandidates.push_back(*itc);
10294               int stNode(c[ci[i]+1]),endNode(isect[0]);
10295               for(int j=0;j<sz+1;j++)
10296                 {
10297                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10298                     {
10299                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10300                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10301                         { mid[j]=*itc; break; }
10302                     }
10303                   stNode=endNode;
10304                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10305                 }
10306             }
10307         }
10308     }
10309   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10310   if(nbOf2DCellsToBeSplit==0)
10311     return ret.retn();
10312   //
10313   int *retPtr(ret->getPointer());
10314   for(int i=0;i<nCell;i++)
10315     if(cells2DToTreat[i])
10316       *retPtr++=i;
10317   //
10318   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10319   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10320   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10321   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10322   if(middleNeedsToBeUsed)
10323     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10324   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10325   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10326   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.
10327   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10328   {
10329     bool areNodesMerged; int newNbOfNodes;
10330     if(nbOfNodesCreated!=0)
10331       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10332   }
10333   return ret.retn();
10334 }
10335
10336 /*!
10337  * 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.
10338  * 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).
10339  * 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
10340  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10341  * 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
10342  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10343  *
10344  * 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
10345  * using new instance, idem for coordinates.
10346  *
10347  * 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.
10348  * 
10349  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10350  *
10351  * \throw If \a this is not coherent.
10352  * \throw If \a this has not spaceDim equal to 2.
10353  * \throw If \a this has not meshDim equal to 2.
10354  * 
10355  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10356  */
10357 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10358 {
10359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10360   checkCoherency();
10361   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10362     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10363   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10364   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10365   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10366   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10367   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10368   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10369   const double *coords(_coords->begin());
10370   int *newciptr(newci->getPointer());
10371   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10372     {
10373       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10374         ret->pushBackSilent(i);
10375       newciptr[1]=newc->getNumberOfTuples();
10376     }
10377   //
10378   if(ret->empty())
10379     return ret.retn();
10380   if(!appendedCoords->empty())
10381     {
10382       appendedCoords->rearrange(2);
10383       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10384       //non const part
10385       setCoords(newCoords);
10386     }
10387   //non const part
10388   setConnectivity(newc,newci,true);
10389   return ret.retn();
10390 }
10391
10392 /*!
10393  * \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.
10394  *                               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.
10395  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10396  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10397  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10398  * \param [out] addCoo - nodes to be append at the end
10399  * \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.
10400  */
10401 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10402                                          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)
10403 {
10404   static const int SPACEDIM=2;
10405   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10406   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10407   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10408   // Build BB tree of all edges in the tool mesh (second mesh)
10409   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10410   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10411   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10412   intersectEdge1.resize(nDescCell1);
10413   colinear2.resize(nDescCell2);
10414   subDiv2.resize(nDescCell2);
10415   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10416
10417   std::vector<int> candidates1(1);
10418   int offset1(m1Desc->getNumberOfNodes());
10419   int offset2(offset1+m2Desc->getNumberOfNodes());
10420   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10421     {
10422       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10423       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10424       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10425         {
10426           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10427           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10428           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10429           candidates1[0]=i;
10430           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10431           // 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
10432           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10433           std::set<INTERP_KERNEL::Node *> nodes;
10434           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10435           std::size_t szz(nodes.size());
10436           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10437           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10438           for(std::size_t iii=0;iii<szz;iii++,itt++)
10439             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10440           // end of protection
10441           // Performs egde cutting:
10442           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10443           delete pol2;
10444           delete pol1;
10445         }
10446       else
10447         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10448         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10449     }
10450 }
10451
10452 /*!
10453  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10454  * It builds the descending connectivity of the two meshes, and then using a binary tree
10455  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10456  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10457  */
10458 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10459                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10460                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10461                                                    std::vector<double>& addCoo,
10462                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10463 {
10464   // Build desc connectivity
10465   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10466   desc2=DataArrayInt::New();
10467   descIndx2=DataArrayInt::New();
10468   revDesc2=DataArrayInt::New();
10469   revDescIndx2=DataArrayInt::New();
10470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10472   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10473   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10474   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10475   std::map<int,int> notUsedMap;
10476   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10477   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10478   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10479 }
10480
10481 /*!
10482  * This method performs the 2nd step of Partition of 2D mesh.
10483  * This method has 4 inputs :
10484  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10485  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10486  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10487  * 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'
10488  * Nodes end up lying consecutively on a cutted edge.
10489  * \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.
10490  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10491  * \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.
10492  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10493  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10494  */
10495 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10496                                            const std::vector<double>& addCoo,
10497                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10498 {
10499   int offset1=m1->getNumberOfNodes();
10500   int ncell=m2->getNumberOfCells();
10501   const int *c=m2->getNodalConnectivity()->getConstPointer();
10502   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10503   const double *coo=m2->getCoords()->getConstPointer();
10504   const double *cooBis=m1->getCoords()->getConstPointer();
10505   int offset2=offset1+m2->getNumberOfNodes();
10506   intersectEdge.resize(ncell);
10507   for(int i=0;i<ncell;i++,cI++)
10508     {
10509       const std::vector<int>& divs=subDiv[i];
10510       int nnode=cI[1]-cI[0]-1;
10511       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10512       std::map<INTERP_KERNEL::Node *, int> mapp22;
10513       for(int j=0;j<nnode;j++)
10514         {
10515           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10516           int nnid=c[(*cI)+j+1];
10517           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10518           mapp22[nn]=nnid+offset1;
10519         }
10520       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10521       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10522         ((*it).second.first)->decrRef();
10523       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10524       std::map<INTERP_KERNEL::Node *,int> mapp3;
10525       for(std::size_t j=0;j<divs.size();j++)
10526         {
10527           int id=divs[j];
10528           INTERP_KERNEL::Node *tmp=0;
10529           if(id<offset1)
10530             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10531           else if(id<offset2)
10532             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10533           else
10534             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10535           addNodes[j]=tmp;
10536           mapp3[tmp]=id;
10537         }
10538       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10539       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10540         (*it)->decrRef();
10541       e->decrRef();
10542     }
10543 }
10544
10545 /*!
10546  * 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).
10547  * 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
10548  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10549  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10550  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10551  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10552  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10553  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10554  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10555  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10556  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10557  * \param [out] cut3DSuf input/output param.
10558  */
10559 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10560                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10561                                                    const int *desc, const int *descIndx, 
10562                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10563 {
10564   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10565   int nbOf3DSurfCell=(int)cut3DSurf.size();
10566   for(int i=0;i<nbOf3DSurfCell;i++)
10567     {
10568       std::vector<int> res;
10569       int offset=descIndx[i];
10570       int nbOfSeg=descIndx[i+1]-offset;
10571       for(int j=0;j<nbOfSeg;j++)
10572         {
10573           int edgeId=desc[offset+j];
10574           int status=cut3DCurve[edgeId];
10575           if(status!=-2)
10576             {
10577               if(status>-1)
10578                 res.push_back(status);
10579               else
10580                 {
10581                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10582                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10583                 }
10584             }
10585         }
10586       switch(res.size())
10587       {
10588         case 2:
10589           {
10590             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10591             break;
10592           }
10593         case 1:
10594         case 0:
10595           {
10596             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10597             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10598             if(res.size()==2)
10599               {
10600                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10601               }
10602             else
10603               {
10604                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10605               }
10606             break;
10607           }
10608         default:
10609           {// case when plane is on a multi colinear edge of a polyhedron
10610             if((int)res.size()==2*nbOfSeg)
10611               {
10612                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10613               }
10614             else
10615               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10616           }
10617       }
10618     }
10619 }
10620
10621 /*!
10622  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10623  * 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).
10624  * 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
10625  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10626  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10627  * \param desc is the descending connectivity 3D->3DSurf
10628  * \param descIndx is the descending connectivity index 3D->3DSurf
10629  */
10630 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10631                                                   const int *desc, const int *descIndx,
10632                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10633 {
10634   checkFullyDefined();
10635   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10636     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10637   const int *nodal3D=_nodal_connec->getConstPointer();
10638   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10639   int nbOfCells=getNumberOfCells();
10640   for(int i=0;i<nbOfCells;i++)
10641     {
10642       std::map<int, std::set<int> > m;
10643       int offset=descIndx[i];
10644       int nbOfFaces=descIndx[i+1]-offset;
10645       int start=-1;
10646       int end=-1;
10647       for(int j=0;j<nbOfFaces;j++)
10648         {
10649           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10650           if(p.first!=-1 && p.second!=-1)
10651             {
10652               if(p.first!=-2)
10653                 {
10654                   start=p.first; end=p.second;
10655                   m[p.first].insert(p.second);
10656                   m[p.second].insert(p.first);
10657                 }
10658               else
10659                 {
10660                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10661                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10662                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10663                   INTERP_KERNEL::NormalizedCellType cmsId;
10664                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10665                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10666                   for(unsigned k=0;k<nbOfNodesSon;k++)
10667                     {
10668                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10669                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10670                     }
10671                 }
10672             }
10673         }
10674       if(m.empty())
10675         continue;
10676       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10677       int prev=end;
10678       while(end!=start)
10679         {
10680           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10681           const std::set<int>& s=(*it).second;
10682           std::set<int> s2; s2.insert(prev);
10683           std::set<int> s3;
10684           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10685           if(s3.size()==1)
10686             {
10687               int val=*s3.begin();
10688               conn.push_back(start);
10689               prev=start;
10690               start=val;
10691             }
10692           else
10693             start=end;
10694         }
10695       conn.push_back(end);
10696       if(conn.size()>3)
10697         {
10698           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10699           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10700           cellIds->pushBackSilent(i);
10701         }
10702     }
10703 }
10704
10705 /*!
10706  * 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
10707  * 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
10708  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10709  * 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
10710  * 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.
10711  * 
10712  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10713  */
10714 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10715 {
10716   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10717   if(sz>=4)
10718     {
10719       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10720       if(cm.getDimension()==2)
10721         {
10722           const int *node=nodalConnBg+1;
10723           int startNode=*node++;
10724           double refX=coords[2*startNode];
10725           for(;node!=nodalConnEnd;node++)
10726             {
10727               if(coords[2*(*node)]<refX)
10728                 {
10729                   startNode=*node;
10730                   refX=coords[2*startNode];
10731                 }
10732             }
10733           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10734           refX=1e300;
10735           double tmp1;
10736           double tmp2[2];
10737           double angle0=-M_PI/2;
10738           //
10739           int nextNode=-1;
10740           int prevNode=-1;
10741           double resRef;
10742           double angleNext=0.;
10743           while(nextNode!=startNode)
10744             {
10745               nextNode=-1;
10746               resRef=1e300;
10747               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10748                 {
10749                   if(*node!=tmpOut.back() && *node!=prevNode)
10750                     {
10751                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10752                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10753                       double res;
10754                       if(angleM<=angle0)
10755                         res=angle0-angleM;
10756                       else
10757                         res=angle0-angleM+2.*M_PI;
10758                       if(res<resRef)
10759                         {
10760                           nextNode=*node;
10761                           resRef=res;
10762                           angleNext=angleM;
10763                         }
10764                     }
10765                 }
10766               if(nextNode!=startNode)
10767                 {
10768                   angle0=angleNext-M_PI;
10769                   if(angle0<-M_PI)
10770                     angle0+=2*M_PI;
10771                   prevNode=tmpOut.back();
10772                   tmpOut.push_back(nextNode);
10773                 }
10774             }
10775           std::vector<int> tmp3(2*(sz-1));
10776           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10777           std::copy(nodalConnBg+1,nodalConnEnd,it);
10778           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10779             {
10780               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10781               return false;
10782             }
10783           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10784             {
10785               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10786               return false;
10787             }
10788           else
10789             {
10790               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10791               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10792               return true;
10793             }
10794         }
10795       else
10796         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10797     }
10798   else
10799     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10800 }
10801
10802 /*!
10803  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10804  * 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.
10805  * 
10806  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10807  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10808  * \param [in,out] arr array in which the remove operation will be done.
10809  * \param [in,out] arrIndx array in the remove operation will modify
10810  * \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])
10811  * \return true if \b arr and \b arrIndx have been modified, false if not.
10812  */
10813 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10814 {
10815   if(!arrIndx || !arr)
10816     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10817   if(offsetForRemoval<0)
10818     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10819   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10820   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10821   int *arrIPtr=arrIndx->getPointer();
10822   *arrIPtr++=0;
10823   int previousArrI=0;
10824   const int *arrPtr=arr->getConstPointer();
10825   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10826   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10827     {
10828       if(*arrIPtr-previousArrI>offsetForRemoval)
10829         {
10830           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10831             {
10832               if(s.find(*work)==s.end())
10833                 arrOut.push_back(*work);
10834             }
10835         }
10836       previousArrI=*arrIPtr;
10837       *arrIPtr=(int)arrOut.size();
10838     }
10839   if(arr->getNumberOfTuples()==(int)arrOut.size())
10840     return false;
10841   arr->alloc((int)arrOut.size(),1);
10842   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10843   return true;
10844 }
10845
10846 /*!
10847  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10848  * (\ref numbering-indirect).
10849  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10850  * The selection of extraction is done standardly in new2old format.
10851  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10852  *
10853  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10854  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10855  * \param [in] arrIn arr origin array from which the extraction will be done.
10856  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10857  * \param [out] arrOut the resulting array
10858  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10859  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10860  */
10861 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10862                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10863 {
10864   if(!arrIn || !arrIndxIn)
10865     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10866   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10867   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10868     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10869   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10870   const int *arrInPtr=arrIn->getConstPointer();
10871   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10872   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10873   if(nbOfGrps<0)
10874     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10875   int maxSizeOfArr=arrIn->getNumberOfTuples();
10876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10878   arrIo->alloc((int)(sz+1),1);
10879   const int *idsIt=idsOfSelectBg;
10880   int *work=arrIo->getPointer();
10881   *work++=0;
10882   int lgth=0;
10883   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10884     {
10885       if(*idsIt>=0 && *idsIt<nbOfGrps)
10886         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10887       else
10888         {
10889           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10890           throw INTERP_KERNEL::Exception(oss.str().c_str());
10891         }
10892       if(lgth>=work[-1])
10893         *work=lgth;
10894       else
10895         {
10896           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10897           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10898           throw INTERP_KERNEL::Exception(oss.str().c_str());
10899         }
10900     }
10901   arro->alloc(lgth,1);
10902   work=arro->getPointer();
10903   idsIt=idsOfSelectBg;
10904   for(std::size_t i=0;i<sz;i++,idsIt++)
10905     {
10906       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10907         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10908       else
10909         {
10910           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10911           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10912           throw INTERP_KERNEL::Exception(oss.str().c_str());
10913         }
10914     }
10915   arrOut=arro.retn();
10916   arrIndexOut=arrIo.retn();
10917 }
10918
10919 /*!
10920  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10921  * (\ref numbering-indirect).
10922  * 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 ).
10923  * The selection of extraction is done standardly in new2old format.
10924  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10925  *
10926  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
10927  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
10928  * \param [in] idsOfSelectStep
10929  * \param [in] arrIn arr origin array from which the extraction will be done.
10930  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10931  * \param [out] arrOut the resulting array
10932  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10933  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10934  */
10935 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10936                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10937 {
10938   if(!arrIn || !arrIndxIn)
10939     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10940   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10941   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10942     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10943   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10944   const int *arrInPtr=arrIn->getConstPointer();
10945   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10946   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10947   if(nbOfGrps<0)
10948     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10949   int maxSizeOfArr=arrIn->getNumberOfTuples();
10950   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10951   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10952   arrIo->alloc((int)(sz+1),1);
10953   int idsIt=idsOfSelectStart;
10954   int *work=arrIo->getPointer();
10955   *work++=0;
10956   int lgth=0;
10957   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10958     {
10959       if(idsIt>=0 && idsIt<nbOfGrps)
10960         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10961       else
10962         {
10963           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10964           throw INTERP_KERNEL::Exception(oss.str().c_str());
10965         }
10966       if(lgth>=work[-1])
10967         *work=lgth;
10968       else
10969         {
10970           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10971           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10972           throw INTERP_KERNEL::Exception(oss.str().c_str());
10973         }
10974     }
10975   arro->alloc(lgth,1);
10976   work=arro->getPointer();
10977   idsIt=idsOfSelectStart;
10978   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10979     {
10980       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10981         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10982       else
10983         {
10984           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10985           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10986           throw INTERP_KERNEL::Exception(oss.str().c_str());
10987         }
10988     }
10989   arrOut=arro.retn();
10990   arrIndexOut=arrIo.retn();
10991 }
10992
10993 /*!
10994  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10995  * 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
10996  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10997  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10998  *
10999  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11000  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11001  * \param [in] arrIn arr origin array from which the extraction will be done.
11002  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11003  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
11004  * \param [in] srcArrIndex index array of \b srcArr
11005  * \param [out] arrOut the resulting array
11006  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11007  * 
11008  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11009  */
11010 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11011                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11012                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11013 {
11014   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11015     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11016   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11017   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11018   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11019   std::vector<bool> v(nbOfTuples,true);
11020   int offset=0;
11021   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11022   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11023   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11024     {
11025       if(*it>=0 && *it<nbOfTuples)
11026         {
11027           v[*it]=false;
11028           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11029         }
11030       else
11031         {
11032           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11033           throw INTERP_KERNEL::Exception(oss.str().c_str());
11034         }
11035     }
11036   srcArrIndexPtr=srcArrIndex->getConstPointer();
11037   arrIo->alloc(nbOfTuples+1,1);
11038   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11039   const int *arrInPtr=arrIn->getConstPointer();
11040   const int *srcArrPtr=srcArr->getConstPointer();
11041   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11042   int *arroPtr=arro->getPointer();
11043   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11044     {
11045       if(v[ii])
11046         {
11047           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11048           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11049         }
11050       else
11051         {
11052           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11053           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11054           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11055         }
11056     }
11057   arrOut=arro.retn();
11058   arrIndexOut=arrIo.retn();
11059 }
11060
11061 /*!
11062  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11063  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11064  *
11065  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11066  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11067  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11068  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11069  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11070  * \param [in] srcArrIndex index array of \b srcArr
11071  * 
11072  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11073  */
11074 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11075                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11076 {
11077   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11078     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11079   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11080   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11081   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11082   int *arrInOutPtr=arrInOut->getPointer();
11083   const int *srcArrPtr=srcArr->getConstPointer();
11084   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11085     {
11086       if(*it>=0 && *it<nbOfTuples)
11087         {
11088           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11089             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11090           else
11091             {
11092               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] !";
11093               throw INTERP_KERNEL::Exception(oss.str().c_str());
11094             }
11095         }
11096       else
11097         {
11098           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11099           throw INTERP_KERNEL::Exception(oss.str().c_str());
11100         }
11101     }
11102 }
11103
11104 /*!
11105  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11106  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11107  * 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]].
11108  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11109  * A negative value in \b arrIn means that it is ignored.
11110  * 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.
11111  * 
11112  * \param [in] arrIn arr origin array from which the extraction will be done.
11113  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11114  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11115  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11116  */
11117 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11118 {
11119   int seed=0,nbOfDepthPeelingPerformed=0;
11120   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11121 }
11122
11123 /*!
11124  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11125  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11126  * 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]].
11127  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11128  * A negative value in \b arrIn means that it is ignored.
11129  * 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.
11130  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11131  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11132  * \param [in] arrIn arr origin array from which the extraction will be done.
11133  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11134  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11135  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11136  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11137  * \sa MEDCouplingUMesh::partitionBySpreadZone
11138  */
11139 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11140 {
11141   nbOfDepthPeelingPerformed=0;
11142   if(!arrIndxIn)
11143     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11144   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11145   if(nbOfTuples<=0)
11146     {
11147       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11148       return ret;
11149     }
11150   //
11151   std::vector<bool> fetched(nbOfTuples,false);
11152   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11153 }
11154
11155 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11156 {
11157   nbOfDepthPeelingPerformed=0;
11158   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11159     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11160   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11161   std::vector<bool> fetched2(nbOfTuples,false);
11162   int i=0;
11163   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11164     {
11165       if(*seedElt>=0 && *seedElt<nbOfTuples)
11166         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11167       else
11168         { 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()); }
11169     }
11170   const int *arrInPtr=arrIn->getConstPointer();
11171   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11172   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11173   std::vector<int> idsToFetch1(seedBg,seedEnd);
11174   std::vector<int> idsToFetch2;
11175   std::vector<int> *idsToFetch=&idsToFetch1;
11176   std::vector<int> *idsToFetchOther=&idsToFetch2;
11177   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11178     {
11179       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11180         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11181           if(!fetched[*it2])
11182             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11183       std::swap(idsToFetch,idsToFetchOther);
11184       idsToFetchOther->clear();
11185       nbOfDepthPeelingPerformed++;
11186     }
11187   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11188   i=0;
11189   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11190   int *retPtr=ret->getPointer();
11191   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11192     if(*it)
11193       *retPtr++=i;
11194   return ret.retn();
11195 }
11196
11197 /*!
11198  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11199  * 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
11200  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11201  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11202  *
11203  * \param [in] start begin of set of ids of the input extraction (included)
11204  * \param [in] end end of set of ids of the input extraction (excluded)
11205  * \param [in] step step of the set of ids in range mode.
11206  * \param [in] arrIn arr origin array from which the extraction will be done.
11207  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11208  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11209  * \param [in] srcArrIndex index array of \b srcArr
11210  * \param [out] arrOut the resulting array
11211  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11212  * 
11213  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11214  */
11215 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11216                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11217                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11218 {
11219   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11220     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11221   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11222   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11223   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11224   int offset=0;
11225   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11226   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11227   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11228   int it=start;
11229   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11230     {
11231       if(it>=0 && it<nbOfTuples)
11232         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11233       else
11234         {
11235           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11236           throw INTERP_KERNEL::Exception(oss.str().c_str());
11237         }
11238     }
11239   srcArrIndexPtr=srcArrIndex->getConstPointer();
11240   arrIo->alloc(nbOfTuples+1,1);
11241   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11242   const int *arrInPtr=arrIn->getConstPointer();
11243   const int *srcArrPtr=srcArr->getConstPointer();
11244   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11245   int *arroPtr=arro->getPointer();
11246   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11247     {
11248       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11249       if(pos<0)
11250         {
11251           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11252           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11253         }
11254       else
11255         {
11256           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11257           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11258         }
11259     }
11260   arrOut=arro.retn();
11261   arrIndexOut=arrIo.retn();
11262 }
11263
11264 /*!
11265  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11266  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11267  *
11268  * \param [in] start begin of set of ids of the input extraction (included)
11269  * \param [in] end end of set of ids of the input extraction (excluded)
11270  * \param [in] step step of the set of ids in range mode.
11271  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11272  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11273  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11274  * \param [in] srcArrIndex index array of \b srcArr
11275  * 
11276  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11277  */
11278 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11279                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11280 {
11281   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11282     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11283   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11284   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11285   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11286   int *arrInOutPtr=arrInOut->getPointer();
11287   const int *srcArrPtr=srcArr->getConstPointer();
11288   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11289   int it=start;
11290   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11291     {
11292       if(it>=0 && it<nbOfTuples)
11293         {
11294           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11295             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11296           else
11297             {
11298               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11299               throw INTERP_KERNEL::Exception(oss.str().c_str());
11300             }
11301         }
11302       else
11303         {
11304           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11305           throw INTERP_KERNEL::Exception(oss.str().c_str());
11306         }
11307     }
11308 }
11309
11310 /*!
11311  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11312  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11313  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11314  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11315  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11316  * 
11317  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11318  */
11319 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11320 {
11321   checkFullyDefined();
11322   int mdim=getMeshDimension();
11323   int spaceDim=getSpaceDimension();
11324   if(mdim!=spaceDim)
11325     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11326   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11327   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11328   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11329   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11330   ret->setCoords(getCoords());
11331   ret->allocateCells((int)partition.size());
11332   //
11333   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11334     {
11335       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11336       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11337       switch(mdim)
11338       {
11339         case 2:
11340           cell=tmp->buildUnionOf2DMesh();
11341           break;
11342         case 3:
11343           cell=tmp->buildUnionOf3DMesh();
11344           break;
11345         default:
11346           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11347       }
11348
11349       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11350     }
11351   //
11352   ret->finishInsertingCells();
11353   return ret.retn();
11354 }
11355
11356 /*!
11357  * This method partitions \b this into contiguous zone.
11358  * This method only needs a well defined connectivity. Coordinates are not considered here.
11359  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11360  */
11361 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11362 {
11363   int nbOfCellsCur=getNumberOfCells();
11364   std::vector<DataArrayInt *> ret;
11365   if(nbOfCellsCur<=0)
11366     return ret;
11367   DataArrayInt *neigh=0,*neighI=0;
11368   computeNeighborsOfCells(neigh,neighI);
11369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11370   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11371   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11372   int seed=0;
11373   while(seed<nbOfCellsCur)
11374     {
11375       int nbOfPeelPerformed=0;
11376       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11377       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11378     }
11379   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11380     ret.push_back((*it).retn());
11381   return ret;
11382 }
11383
11384 /*!
11385  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11386  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11387  *
11388  * \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.
11389  * \return a newly allocated DataArrayInt to be managed by the caller.
11390  * \throw In case of \a code has not the right format (typically of size 3*n)
11391  */
11392 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11393 {
11394   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11395   std::size_t nb=code.size()/3;
11396   if(code.size()%3!=0)
11397     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11398   ret->alloc((int)nb,2);
11399   int *retPtr=ret->getPointer();
11400   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11401     {
11402       retPtr[0]=code[3*i+2];
11403       retPtr[1]=code[3*i+2]+code[3*i+1];
11404     }
11405   return ret.retn();
11406 }
11407
11408 /*!
11409  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11410  * All cells in \a this are expected to be linear 3D cells.
11411  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11412  * It leads to an increase to number of cells.
11413  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11414  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11415  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11416  *
11417  * \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.
11418  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11419  * \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. 
11420  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11421  *          an id of old cell producing it. The caller is to delete this array using
11422  *         decrRef() as it is no more needed.
11423  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11424  *
11425  * \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
11426  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11427  * 
11428  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11429  * \throw If \a this is not fully constituted with linear 3D cells.
11430  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11431  */
11432 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11433 {
11434   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11435   checkConnectivityFullyDefined();
11436   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11437     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11438   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11439   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11440   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11441   int *retPt(ret->getPointer());
11442   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11443   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11444   const int *oldc(_nodal_connec->begin());
11445   const int *oldci(_nodal_connec_index->begin());
11446   const double *coords(_coords->begin());
11447   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11448     {
11449       std::vector<int> a; std::vector<double> b;
11450       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11451       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11452       const int *aa(&a[0]);
11453       if(!b.empty())
11454         {
11455           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11456             if(*it<0)
11457               *it=(-(*(it))-1+nbNodes);
11458           addPts->insertAtTheEnd(b.begin(),b.end());
11459           nbNodes+=(int)b.size()/3;
11460         }
11461       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11462         newConn->insertAtTheEnd(aa,aa+4);
11463     }
11464   if(!addPts->empty())
11465     {
11466       addPts->rearrange(3);
11467       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11468       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11469       ret0->setCoords(addPts);
11470     }
11471   else
11472     {
11473       nbOfAdditionalPoints=0;
11474       ret0->setCoords(getCoords());
11475     }
11476   ret0->setNodalConnectivity(newConn);
11477   //
11478   ret->computeOffsets2();
11479   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11480   return ret0.retn();
11481 }
11482
11483 /*!
11484  * 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). 
11485  *
11486  * \sa MEDCouplingUMesh::split2DCells
11487  */
11488 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11489 {
11490   checkConnectivityFullyDefined();
11491   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11492   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11493   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11494   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11495   int prevPosOfCi(ciPtr[0]);
11496   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11497     {
11498       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11499       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11500       for(int j=0;j<sz;j++)
11501         {
11502           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11503           for(int k=0;k<sz2;k++)
11504             *cPtr++=subPtr[offset2+k];
11505           if(j!=sz-1)
11506             *cPtr++=oldConn[prevPosOfCi+j+2];
11507           deltaSz+=sz2;
11508         }
11509       prevPosOfCi=ciPtr[1];
11510       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11511     }
11512   if(c->end()!=cPtr)
11513     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11514   _nodal_connec->decrRef();
11515   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11516 }
11517
11518 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11519 {
11520   if(id!=-1)
11521     return id;
11522   else
11523     {
11524       int ret(nodesCnter++);
11525       double newPt[2];
11526       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11527       addCoo.insertAtTheEnd(newPt,newPt+2);
11528       return ret;
11529     }
11530 }
11531
11532 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11533 {
11534   if(id!=-1)
11535     return id;
11536   else
11537     {
11538       int ret(nodesCnter++);
11539       double newPt[2];
11540       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11541       addCoo.insertAtTheEnd(newPt,newPt+2);
11542       return ret;
11543     }
11544 }
11545
11546
11547 /// @cond INTERNAL
11548
11549 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)
11550 {
11551   int tmp[3];
11552   int trueStart(start>=0?start:nbOfEdges+start);
11553   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11554   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11555   if(linOrArc)
11556     {
11557       if(stp-start>1)
11558         {
11559           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11560           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11561           middles.push_back(tmp3+offset);
11562         }
11563       else
11564         middles.push_back(connBg[trueStart+nbOfEdges]);
11565     }
11566 }
11567
11568 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)
11569 {
11570   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11571   newConnOfCell->pushBackSilent(tmpEnd);
11572   if(linOrArc)
11573     {
11574       if(stp-start>1)
11575         {
11576           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11577           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11578           middles.push_back(tmp3+offset);
11579         }
11580       else
11581         middles.push_back(connBg[start+nbOfEdges]);
11582     }
11583 }
11584
11585 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)
11586 {
11587   // only the quadratic point to deal with:
11588   if(linOrArc)
11589     {
11590       if(stp-start>1)
11591         {
11592           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11593           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11594           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11595           middles.push_back(tmp3+offset);
11596         }
11597       else
11598         middles.push_back(connBg[start+nbOfEdges]);
11599     }
11600 }
11601
11602 /// @endcond
11603
11604 /*!
11605  * 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 ) .
11606  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11607  */
11608 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11609 {
11610   std::size_t sz(std::distance(connBg,connEnd));
11611   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11612     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11613   sz--;
11614   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11615   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11616   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11617   unsigned nbOfHit(0); // number of fusions operated
11618   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11619   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
11620   INTERP_KERNEL::NormalizedCellType typeOfSon;
11621   std::vector<int> middles;
11622   bool ret(false);
11623   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11624     {
11625       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11626       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11627       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11628       posEndElt = posBaseElt+1;
11629
11630       // Look backward first: are the final edges of the cells colinear with the first ones?
11631       // This initializes posBaseElt.
11632       if(nbOfTurn==0)
11633         {
11634           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11635             {
11636               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11637               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11638               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11639               bool isColinear=eint->areColinears();
11640               if(isColinear)
11641                 {
11642                   nbOfHit++;
11643                   posBaseElt--;
11644                   ret=true;
11645                 }
11646               delete eint;
11647               eCand->decrRef();
11648               if(!isColinear)
11649                 break;
11650             }
11651         }
11652       // Now move forward:
11653       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11654       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11655         {
11656           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11657           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11658           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11659           bool isColinear(eint->areColinears());
11660           if(isColinear)
11661             {
11662               nbOfHit++;
11663               posEndElt++;
11664               ret=true;
11665             }
11666           delete eint;
11667           eCand->decrRef();
11668           if(!isColinear)
11669               break;
11670         }
11671       //push [posBaseElt,posEndElt) in newConnOfCell using e
11672       // 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!
11673       if(nbOfTurn==0)
11674         // at the begining of the connectivity (insert type)
11675         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11676       else if((nbOfHit+nbOfTurn) != (nbs-1))
11677         // in the middle
11678         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11679       if ((nbOfHit+nbOfTurn) == (nbs-1))
11680         // at the end (only quad points to deal with)
11681         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11682       posBaseElt=posEndElt;
11683       e->decrRef();
11684     }
11685   if(!middles.empty())
11686     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11687   return ret;
11688 }
11689
11690 /*!
11691  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11692  *
11693  * \return  int - the number of new nodes created.
11694  * \sa MEDCouplingUMesh::split2DCells
11695  */
11696 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11697 {
11698   checkCoherency();
11699   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11700   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11701   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11702   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11703   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11704   const double *oldCoordsPtr(getCoords()->begin());
11705   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11706   int prevPosOfCi(ciPtr[0]);
11707   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11708     {
11709       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11710       for(int j=0;j<sz;j++)
11711         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11712       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11713       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11714         {
11715           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11716           if(sz2==0)
11717             {
11718               if(j<sz-1)
11719                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11720               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11721               continue;
11722             }
11723           std::vector<INTERP_KERNEL::Node *> ns(3);
11724           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11725           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11726           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11727           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11728           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11729             {
11730               cPtr[1]=subPtr[offset2+k];
11731               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11732             }
11733           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11734           if(j!=sz-1)
11735             { cPtr[1]=tmpEnd; }
11736           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11737         }
11738       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11739       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11740     }
11741   if(c->end()!=cPtr)
11742     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11743   _nodal_connec->decrRef();
11744   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11745   addCoo->rearrange(2);
11746   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11747   setCoords(coo);
11748   return addCoo->getNumberOfTuples();
11749 }
11750
11751 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11752 {
11753   if(nodalConnec && nodalConnecIndex)
11754     {
11755       types.clear();
11756       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11757       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11758       if(nbOfElem>0)
11759         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11760           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11761     }
11762 }
11763
11764 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11765     _own_cell(true),_cell_id(-1),_nb_cell(0)
11766 {
11767   if(mesh)
11768     {
11769       mesh->incrRef();
11770       _nb_cell=mesh->getNumberOfCells();
11771     }
11772 }
11773
11774 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11775 {
11776   if(_mesh)
11777     _mesh->decrRef();
11778   if(_own_cell)
11779     delete _cell;
11780 }
11781
11782 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11783     _own_cell(false),_cell_id(bg-1),
11784     _nb_cell(end)
11785 {
11786   if(mesh)
11787     mesh->incrRef();
11788 }
11789
11790 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11791 {
11792   _cell_id++;
11793   if(_cell_id<_nb_cell)
11794     {
11795       _cell->next();
11796       return _cell;
11797     }
11798   else
11799     return 0;
11800 }
11801
11802 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11803 {
11804   if(_mesh)
11805     _mesh->incrRef();
11806 }
11807
11808 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11809 {
11810   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11811 }
11812
11813 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11814 {
11815   if(_mesh)
11816     _mesh->decrRef();
11817 }
11818
11819 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11820     _itc(itc),
11821     _bg(bg),_end(end)
11822 {
11823   if(_mesh)
11824     _mesh->incrRef();
11825 }
11826
11827 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11828 {
11829   if(_mesh)
11830     _mesh->decrRef();
11831 }
11832
11833 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11834 {
11835   return _type;
11836 }
11837
11838 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11839 {
11840   return _end-_bg;
11841 }
11842
11843 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11844 {
11845   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11846 }
11847
11848 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11849 {
11850   if(mesh)
11851     {
11852       mesh->incrRef();
11853       _nb_cell=mesh->getNumberOfCells();
11854     }
11855 }
11856
11857 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11858 {
11859   if(_mesh)
11860     _mesh->decrRef();
11861   delete _cell;
11862 }
11863
11864 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11865 {
11866   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11867   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11868   if(_cell_id<_nb_cell)
11869     {
11870       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11871       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11872       int startId=_cell_id;
11873       _cell_id+=nbOfElems;
11874       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11875     }
11876   else
11877     return 0;
11878 }
11879
11880 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11881 {
11882   if(mesh)
11883     {
11884       _conn=mesh->getNodalConnectivity()->getPointer();
11885       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11886     }
11887 }
11888
11889 void MEDCouplingUMeshCell::next()
11890 {
11891   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11892     {
11893       _conn+=_conn_lgth;
11894       _conn_indx++;
11895     }
11896   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11897 }
11898
11899 std::string MEDCouplingUMeshCell::repr() const
11900 {
11901   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11902     {
11903       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11904       oss << " : ";
11905       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11906       return oss.str();
11907     }
11908   else
11909     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11910 }
11911
11912 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11913 {
11914   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11915     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11916   else
11917     return INTERP_KERNEL::NORM_ERROR;
11918 }
11919
11920 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11921 {
11922   lgth=_conn_lgth;
11923   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11924     return _conn;
11925   else
11926     return 0;
11927 }