Salome HOME
fix conflict
[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 MEDCouplingMesh which is a full copy of \a this one. No data is shared
75  * between \a this and the new mesh.
76  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
77  *          delete this mesh using decrRef() as it is no more needed. 
78  */
79 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
80 {
81   return clone(true);
82 }
83
84 /*!
85  * Returns a new MEDCouplingMesh which is a copy of \a this one.
86  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
87  * this mesh are shared by the new mesh.
88  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
89  *          delete this mesh using decrRef() as it is no more needed. 
90  */
91 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
92 {
93   return new MEDCouplingUMesh(*this,recDeepCpy);
94 }
95
96 /*!
97  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
98  * The coordinates are shared between \a this and the returned instance.
99  * 
100  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
101  * \sa MEDCouplingUMesh::deepCpy
102  */
103 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
104 {
105   checkConnectivityFullyDefined();
106   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
107   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
108   ret->setConnectivity(c,ci);
109   return ret.retn();
110 }
111
112 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
113 {
114   if(!other)
115     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
116   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
117   if(!otherC)
118     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
119   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
120   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
121 }
122
123 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
124 {
125   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
126   return ret;
127 }
128
129 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
130 {
131   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
132   ret.push_back(_nodal_connec);
133   ret.push_back(_nodal_connec_index);
134   return ret;
135 }
136
137 void MEDCouplingUMesh::updateTime() const
138 {
139   MEDCouplingPointSet::updateTime();
140   if(_nodal_connec)
141     {
142       updateTimeWith(*_nodal_connec);
143     }
144   if(_nodal_connec_index)
145     {
146       updateTimeWith(*_nodal_connec_index);
147     }
148 }
149
150 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
151 {
152 }
153
154 /*!
155  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
156  * then \a this mesh is most probably is writable, exchangeable and available for most
157  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
158  * this method to check that all is in order with \a this mesh.
159  *  \throw If the mesh dimension is not set.
160  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
161  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
162  *  \throw If the connectivity data array has more than one component.
163  *  \throw If the connectivity data array has a named component.
164  *  \throw If the connectivity index data array has more than one component.
165  *  \throw If the connectivity index data array has a named component.
166  */
167 void MEDCouplingUMesh::checkCoherency() const
168 {
169   if(_mesh_dim<-1)
170     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
171   if(_mesh_dim!=-1)
172     MEDCouplingPointSet::checkCoherency();
173   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
174     {
175       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
176         {
177           std::ostringstream message;
178           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
179           throw INTERP_KERNEL::Exception(message.str().c_str());
180         }
181     }
182   if(_nodal_connec)
183     {
184       if(_nodal_connec->getNumberOfComponents()!=1)
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
186       if(_nodal_connec->getInfoOnComponent(0)!="")
187         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
188     }
189   else
190     if(_mesh_dim!=-1)
191       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
192   if(_nodal_connec_index)
193     {
194       if(_nodal_connec_index->getNumberOfComponents()!=1)
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
196       if(_nodal_connec_index->getInfoOnComponent(0)!="")
197         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
198     }
199   else
200     if(_mesh_dim!=-1)
201       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
202 }
203
204 /*!
205  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
206  * then \a this mesh is most probably is writable, exchangeable and available for all
207  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
208  * method thoroughly checks the nodal connectivity.
209  *  \param [in] eps - a not used parameter.
210  *  \throw If the mesh dimension is not set.
211  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
212  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
213  *  \throw If the connectivity data array has more than one component.
214  *  \throw If the connectivity data array has a named component.
215  *  \throw If the connectivity index data array has more than one component.
216  *  \throw If the connectivity index data array has a named component.
217  *  \throw If number of nodes defining an element does not correspond to the type of element.
218  *  \throw If the nodal connectivity includes an invalid node id.
219  */
220 void MEDCouplingUMesh::checkCoherency1(double eps) const
221 {
222   checkCoherency();
223   if(_mesh_dim==-1)
224     return ;
225   int meshDim=getMeshDimension();
226   int nbOfNodes=getNumberOfNodes();
227   int nbOfCells=getNumberOfCells();
228   const int *ptr=_nodal_connec->getConstPointer();
229   const int *ptrI=_nodal_connec_index->getConstPointer();
230   for(int i=0;i<nbOfCells;i++)
231     {
232       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
233       if((int)cm.getDimension()!=meshDim)
234         {
235           std::ostringstream oss;
236           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
237           throw INTERP_KERNEL::Exception(oss.str().c_str());
238         }
239       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
240       if(!cm.isDynamic())
241         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
242           {
243             std::ostringstream oss;
244             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
245             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
246             throw INTERP_KERNEL::Exception(oss.str().c_str());
247           }
248       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
249         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
250           {
251             std::ostringstream oss;
252             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
253             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
254             throw INTERP_KERNEL::Exception(oss.str().c_str());
255           }
256       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
257         {
258           int nodeId=*w;
259           if(nodeId>=0)
260             {
261               if(nodeId>=nbOfNodes)
262                 {
263                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
264                   throw INTERP_KERNEL::Exception(oss.str().c_str());
265                 }
266             }
267           else if(nodeId<-1)
268             {
269               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
270               throw INTERP_KERNEL::Exception(oss.str().c_str());
271             }
272           else
273             {
274               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
275                 {
276                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
277                   throw INTERP_KERNEL::Exception(oss.str().c_str());
278                 }
279             }
280         }
281     }
282 }
283
284
285 /*!
286  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
287  * then \a this mesh is most probably is writable, exchangeable and available for all
288  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
289  *  \param [in] eps - a not used parameter.
290  *  \throw If the mesh dimension is not set.
291  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
292  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
293  *  \throw If the connectivity data array has more than one component.
294  *  \throw If the connectivity data array has a named component.
295  *  \throw If the connectivity index data array has more than one component.
296  *  \throw If the connectivity index data array has a named component.
297  *  \throw If number of nodes defining an element does not correspond to the type of element.
298  *  \throw If the nodal connectivity includes an invalid node id.
299  */
300 void MEDCouplingUMesh::checkCoherency2(double eps) const
301 {
302   checkCoherency1(eps);
303 }
304
305 /*!
306  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
307  * elements contained in the mesh. For more info on the mesh dimension see
308  * \ref MEDCouplingUMeshPage.
309  *  \param [in] meshDim - a new mesh dimension.
310  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
311  */
312 void MEDCouplingUMesh::setMeshDimension(int meshDim)
313 {
314   if(meshDim<-1 || meshDim>3)
315     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
316   _mesh_dim=meshDim;
317   declareAsNew();
318 }
319
320 /*!
321  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
322  * 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.
323  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
324  *
325  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
326  *
327  *  \if ENABLE_EXAMPLES
328  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
329  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
330  *  \endif
331  */
332 void MEDCouplingUMesh::allocateCells(int nbOfCells)
333 {
334   if(nbOfCells<0)
335     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
336   if(_nodal_connec_index)
337     {
338       _nodal_connec_index->decrRef();
339     }
340   if(_nodal_connec)
341     {
342       _nodal_connec->decrRef();
343     }
344   _nodal_connec_index=DataArrayInt::New();
345   _nodal_connec_index->reserve(nbOfCells+1);
346   _nodal_connec_index->pushBackSilent(0);
347   _nodal_connec=DataArrayInt::New();
348   _nodal_connec->reserve(2*nbOfCells);
349   _types.clear();
350   declareAsNew();
351 }
352
353 /*!
354  * Appends a cell to the connectivity array. For deeper understanding what is
355  * happening see \ref MEDCouplingUMeshNodalConnectivity.
356  *  \param [in] type - type of cell to add.
357  *  \param [in] size - number of nodes constituting this cell.
358  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
359  * 
360  *  \if ENABLE_EXAMPLES
361  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
362  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
363  *  \endif
364  */
365 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
366 {
367   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
368   if(_nodal_connec_index==0)
369     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
370   if((int)cm.getDimension()==_mesh_dim)
371     {
372       if(!cm.isDynamic())
373         if(size!=(int)cm.getNumberOfNodes())
374           {
375             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
376             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
377             throw INTERP_KERNEL::Exception(oss.str().c_str());
378           }
379       int idx=_nodal_connec_index->back();
380       int val=idx+size+1;
381       _nodal_connec_index->pushBackSilent(val);
382       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
383       _types.insert(type);
384     }
385   else
386     {
387       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
388       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
389       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
390       throw INTERP_KERNEL::Exception(oss.str().c_str());
391     }
392 }
393
394 /*!
395  * Compacts data arrays to release unused memory. This method is to be called after
396  * finishing cell insertion using \a this->insertNextCell().
397  * 
398  *  \if ENABLE_EXAMPLES
399  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
400  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
401  *  \endif
402  */
403 void MEDCouplingUMesh::finishInsertingCells()
404 {
405   _nodal_connec->pack();
406   _nodal_connec_index->pack();
407   _nodal_connec->declareAsNew();
408   _nodal_connec_index->declareAsNew();
409   updateTime();
410 }
411
412 /*!
413  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
414  * Useful for python users.
415  */
416 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
417 {
418   return new MEDCouplingUMeshCellIterator(this);
419 }
420
421 /*!
422  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
423  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
424  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
425  * Useful for python users.
426  */
427 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
428 {
429   if(!checkConsecutiveCellTypes())
430     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
431   return new MEDCouplingUMeshCellByTypeEntry(this);
432 }
433
434 /*!
435  * Returns a set of all cell types available in \a this mesh.
436  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
437  * \warning this method does not throw any exception even if \a this is not defined.
438  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
439  */
440 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
441 {
442   return _types;
443 }
444
445 /*!
446  * This method returns the sorted list of geometric types in \a this.
447  * 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
448  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
449  *
450  * \throw if connectivity in \a this is not correctly defined.
451  *  
452  * \sa MEDCouplingMesh::getAllGeoTypes
453  */
454 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
455 {
456   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
457   checkConnectivityFullyDefined();
458   int nbOfCells(getNumberOfCells());
459   if(nbOfCells==0)
460     return ret;
461   if(getMeshLength()<1)
462     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
463   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
464   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
465   for(int i=1;i<nbOfCells;i++,ci++)
466     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
467       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
468   return ret;
469 }
470
471 /*!
472  * This method is a method that compares \a this and \a other.
473  * This method compares \b all attributes, even names and component names.
474  */
475 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
476 {
477   if(!other)
478     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
479   std::ostringstream oss; oss.precision(15);
480   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
481   if(!otherC)
482     {
483       reason="mesh given in input is not castable in MEDCouplingUMesh !";
484       return false;
485     }
486   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
487     return false;
488   if(_mesh_dim!=otherC->_mesh_dim)
489     {
490       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
491       reason=oss.str();
492       return false;
493     }
494   if(_types!=otherC->_types)
495     {
496       oss << "umesh geometric type mismatch :\nThis geometric types are :";
497       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
498         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
499       oss << "\nOther geometric types are :";
500       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
501         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
502       reason=oss.str();
503       return false;
504     }
505   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
506     if(_nodal_connec==0 || otherC->_nodal_connec==0)
507       {
508         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
509         return false;
510       }
511   if(_nodal_connec!=otherC->_nodal_connec)
512     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
513       {
514         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
515         return false;
516       }
517   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
518     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
519       {
520         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
521         return false;
522       }
523   if(_nodal_connec_index!=otherC->_nodal_connec_index)
524     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
525       {
526         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
527         return false;
528       }
529   return true;
530 }
531
532 /*!
533  * Checks if data arrays of this mesh (node coordinates, nodal
534  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
535  * not considered.
536  *  \param [in] other - the mesh to compare with.
537  *  \param [in] prec - precision value used to compare node coordinates.
538  *  \return bool - \a true if the two meshes are same.
539  */
540 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
541 {
542   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
543   if(!otherC)
544     return false;
545   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
546     return false;
547   if(_mesh_dim!=otherC->_mesh_dim)
548     return false;
549   if(_types!=otherC->_types)
550     return false;
551   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
552     if(_nodal_connec==0 || otherC->_nodal_connec==0)
553       return false;
554   if(_nodal_connec!=otherC->_nodal_connec)
555     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
556       return false;
557   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
558     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
559       return false;
560   if(_nodal_connec_index!=otherC->_nodal_connec_index)
561     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
562       return false;
563   return true;
564 }
565
566 /*!
567  * Checks if \a this and \a other meshes are geometrically equivalent with high
568  * probability, else an exception is thrown. The meshes are considered equivalent if
569  * (1) meshes contain the same number of nodes and the same number of elements of the
570  * same types (2) three cells of the two meshes (first, last and middle) are based
571  * on coincident nodes (with a specified precision).
572  *  \param [in] other - the mesh to compare with.
573  *  \param [in] prec - the precision used to compare nodes of the two meshes.
574  *  \throw If the two meshes do not match.
575  */
576 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
577 {
578   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
579   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
580   if(!otherC)
581     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
582 }
583
584 /*!
585  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
586  * cells each node belongs to.
587  * \warning For speed reasons, this method does not check if node ids in the nodal
588  *          connectivity correspond to the size of node coordinates array.
589  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
590  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
591  *        dividing cell ids in \a revNodal into groups each referring to one
592  *        node. Its every element (except the last one) is an index pointing to the
593  *         first id of a group of cells. For example cells sharing the node #1 are 
594  *        described by following range of indices: 
595  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
596  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
597  *        Number of cells sharing the *i*-th node is
598  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
599  * \throw If the coordinates array is not set.
600  * \throw If the nodal connectivity of cells is not defined.
601  * 
602  * \if ENABLE_EXAMPLES
603  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
604  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
605  * \endif
606  */
607 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
608 {
609   checkFullyDefined();
610   int nbOfNodes=getNumberOfNodes();
611   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
612   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
613   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
614   const int *conn=_nodal_connec->getConstPointer();
615   const int *connIndex=_nodal_connec_index->getConstPointer();
616   int nbOfCells=getNumberOfCells();
617   int nbOfEltsInRevNodal=0;
618   for(int eltId=0;eltId<nbOfCells;eltId++)
619     {
620       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
621       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
622       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
623         if(*iter>=0)//for polyhedrons
624           {
625             nbOfEltsInRevNodal++;
626             revNodalIndxPtr[(*iter)+1]++;
627           }
628     }
629   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
630   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
631   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
632   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
633   for(int eltId=0;eltId<nbOfCells;eltId++)
634     {
635       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
636       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
637       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
638         if(*iter>=0)//for polyhedrons
639           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
640     }
641 }
642
643 /// @cond INTERNAL
644
645 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
646 {
647   return id;
648 }
649
650 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
651 {
652   if(!compute)
653     return id+1;
654   else
655     {
656       if(cm.getOrientationStatus(nb,conn1,conn2))
657         return id+1;
658       else
659         return -(id+1);
660     }
661 }
662
663 class MinusOneSonsGenerator
664 {
665 public:
666   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
667   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
668   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
669   static const int DELTA=1;
670 private:
671   const INTERP_KERNEL::CellModel& _cm;
672 };
673
674 class MinusOneSonsGeneratorBiQuadratic
675 {
676 public:
677   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
678   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
679   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
680   static const int DELTA=1;
681 private:
682   const INTERP_KERNEL::CellModel& _cm;
683 };
684
685 class MinusTwoSonsGenerator
686 {
687 public:
688   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
689   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
690   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
691   static const int DELTA=2;
692 private:
693   const INTERP_KERNEL::CellModel& _cm;
694 };
695
696 /// @endcond
697
698 /*!
699  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
700  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
701  * describing correspondence between cells of \a this and the result meshes are
702  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
703  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
704  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
705  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
706  * \warning For speed reasons, this method does not check if node ids in the nodal
707  *          connectivity correspond to the size of node coordinates array.
708  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
709  *          to write this mesh to the MED file, its cells must be sorted using
710  *          sortCellsInMEDFileFrmt().
711  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
712  *         each cell of \a this mesh.
713  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
714  *        dividing cell ids in \a desc into groups each referring to one
715  *        cell of \a this mesh. Its every element (except the last one) is an index
716  *        pointing to the first id of a group of cells. For example cells of the
717  *        result mesh bounding the cell #1 of \a this mesh are described by following
718  *        range of indices:
719  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
720  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
721  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
722  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
723  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
724  *         by each cell of the result mesh.
725  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
726  *        in the result mesh,
727  *        dividing cell ids in \a revDesc into groups each referring to one
728  *        cell of the result mesh the same way as \a descIndx divides \a desc.
729  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
730  *        delete this mesh using decrRef() as it is no more needed.
731  *  \throw If the coordinates array is not set.
732  *  \throw If the nodal connectivity of cells is node defined.
733  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
734  *         revDescIndx == NULL.
735  * 
736  *  \if ENABLE_EXAMPLES
737  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
738  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
739  *  \endif
740  * \sa buildDescendingConnectivity2()
741  */
742 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
743 {
744   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
745 }
746
747 /*!
748  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
749  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
750  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
751  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
752  * \sa MEDCouplingUMesh::buildDescendingConnectivity
753  */
754 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
755 {
756   checkFullyDefined();
757   if(getMeshDimension()!=3)
758     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
759   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
760 }
761
762 /*!
763  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
764  * this->getMeshDimension(), that bound cells of \a this mesh. In
765  * addition arrays describing correspondence between cells of \a this and the result
766  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
767  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
768  *  mesh. This method differs from buildDescendingConnectivity() in that apart
769  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
770  * result meshes. So a positive id means that order of nodes in corresponding cells
771  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
772  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
773  * i.e. cell ids are one-based.
774  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
775  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
776  * \warning For speed reasons, this method does not check if node ids in the nodal
777  *          connectivity correspond to the size of node coordinates array.
778  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
779  *          to write this mesh to the MED file, its cells must be sorted using
780  *          sortCellsInMEDFileFrmt().
781  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
782  *         each cell of \a this mesh.
783  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
784  *        dividing cell ids in \a desc into groups each referring to one
785  *        cell of \a this mesh. Its every element (except the last one) is an index
786  *        pointing to the first id of a group of cells. For example cells of the
787  *        result mesh bounding the cell #1 of \a this mesh are described by following
788  *        range of indices:
789  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
790  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
791  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
792  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
793  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
794  *         by each cell of the result mesh.
795  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
796  *        in the result mesh,
797  *        dividing cell ids in \a revDesc into groups each referring to one
798  *        cell of the result mesh the same way as \a descIndx divides \a desc.
799  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
800  *        shares the node coordinates array with \a this mesh. The caller is to
801  *        delete this mesh using decrRef() as it is no more needed.
802  *  \throw If the coordinates array is not set.
803  *  \throw If the nodal connectivity of cells is node defined.
804  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
805  *         revDescIndx == NULL.
806  * 
807  *  \if ENABLE_EXAMPLES
808  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
809  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
810  *  \endif
811  * \sa buildDescendingConnectivity()
812  */
813 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
814 {
815   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
816 }
817
818 /*!
819  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
820  * For speed reasons no check of this will be done. This method calls
821  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
822  * This method lists cell by cell in \b this which are its neighbors. To compute the result
823  * only connectivities are considered.
824  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
825  * The format of return is hence \ref numbering-indirect.
826  *
827  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
828  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
829  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
830  * is equal to the last values in \b neighborsIndx.
831  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
832  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
833  */
834 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
835 {
836   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
838   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
839   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
840   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
841   meshDM1=0;
842   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
843 }
844
845 /*!
846  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
847  * of MEDCouplingUMesh::computeNeighborsOfCells.
848  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
849  * typically the case to extract a set a neighbours,
850  * excluding a set of meshdim-1 cells in input descending connectivity.
851  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
852  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
853  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
854  * are considered.
855  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
856  *
857  * \param [in] desc descending connectivity array.
858  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
859  * \param [in] revDesc reverse descending connectivity array.
860  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
861  * \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
862  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
863  * \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.
864  */
865 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
866                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
867 {
868   if(!desc || !descIndx || !revDesc || !revDescIndx)
869     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
870   const int *descPtr=desc->getConstPointer();
871   const int *descIPtr=descIndx->getConstPointer();
872   const int *revDescPtr=revDesc->getConstPointer();
873   const int *revDescIPtr=revDescIndx->getConstPointer();
874   //
875   int nbCells=descIndx->getNumberOfTuples()-1;
876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
878   int *out1Ptr=out1->getPointer();
879   *out1Ptr++=0;
880   out0->reserve(desc->getNumberOfTuples());
881   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
882     {
883       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
884         {
885           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
886           s.erase(i);
887           out0->insertAtTheEnd(s.begin(),s.end());
888         }
889       *out1Ptr=out0->getNumberOfTuples();
890     }
891   neighbors=out0.retn();
892   neighborsIndx=out1.retn();
893 }
894
895 /*!
896  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
897  * For speed reasons no check of this will be done. This method calls
898  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
899  * This method lists node by node in \b this which are its neighbors. To compute the result
900  * only connectivities are considered.
901  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
902  *
903  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
904  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
905  * parameter allows to select the right part in this array (\ref numbering-indirect).
906  * The number of tuples is equal to the last values in \b neighborsIndx.
907  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
908  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
909  */
910 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
911 {
912   checkFullyDefined();
913   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
914   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
915   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
916   switch(mdim)
917   {
918     case 3:
919       {
920         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
921         break;
922       }
923     case 2:
924       {
925         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
926         break;
927       }
928     case 1:
929       {
930         mesh1D=const_cast<MEDCouplingUMesh *>(this);
931         mesh1D->incrRef();
932         break;
933       }
934     default:
935       {
936         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
937       }
938   }
939   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
940   mesh1D->getReverseNodalConnectivity(desc,descIndx);
941   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
942   ret0->alloc(desc->getNumberOfTuples(),1);
943   int *r0Pt(ret0->getPointer());
944   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
945   for(int i=0;i<nbNodes;i++,rni++)
946     {
947       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
948         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
949     }
950   neighbors=ret0.retn();
951   neighborsIdx=descIndx.retn();
952 }
953
954 /// @cond INTERNAL
955
956 /*!
957  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
958  * For speed reasons no check of this will be done.
959  */
960 template<class SonsGenerator>
961 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
962 {
963   if(!desc || !descIndx || !revDesc || !revDescIndx)
964     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
965   checkConnectivityFullyDefined();
966   int nbOfCells=getNumberOfCells();
967   int nbOfNodes=getNumberOfNodes();
968   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
969   int *revNodalIndxPtr=revNodalIndx->getPointer();
970   const int *conn=_nodal_connec->getConstPointer();
971   const int *connIndex=_nodal_connec_index->getConstPointer();
972   std::string name="Mesh constituent of "; name+=getName();
973   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
974   ret->setCoords(getCoords());
975   ret->allocateCells(2*nbOfCells);
976   descIndx->alloc(nbOfCells+1,1);
977   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
978   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
979   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
980     {
981       int pos=connIndex[eltId];
982       int posP1=connIndex[eltId+1];
983       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
984       SonsGenerator sg(cm);
985       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
986       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
987       for(unsigned i=0;i<nbOfSons;i++)
988         {
989           INTERP_KERNEL::NormalizedCellType cmsId;
990           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
991           for(unsigned k=0;k<nbOfNodesSon;k++)
992             if(tmp[k]>=0)
993               revNodalIndxPtr[tmp[k]+1]++;
994           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
995           revDesc2->pushBackSilent(eltId);
996         }
997       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
998     }
999   int nbOfCellsM1=ret->getNumberOfCells();
1000   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
1001   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
1002   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
1003   int *revNodalPtr=revNodal->getPointer();
1004   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
1005   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
1006   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
1007     {
1008       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
1009       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
1010       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
1011         if(*iter>=0)//for polyhedrons
1012           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
1013     }
1014   //
1015   DataArrayInt *commonCells=0,*commonCellsI=0;
1016   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1017   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1018   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1019   int newNbOfCellsM1=-1;
1020   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1021                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1022   std::vector<bool> isImpacted(nbOfCellsM1,false);
1023   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1024     for(int work2=work[0];work2!=work[1];work2++)
1025       isImpacted[commonCellsPtr[work2]]=true;
1026   const int *o2nM1Ptr=o2nM1->getConstPointer();
1027   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1028   const int *n2oM1Ptr=n2oM1->getConstPointer();
1029   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1030   ret2->copyTinyInfoFrom(this);
1031   desc->alloc(descIndx->back(),1);
1032   int *descPtr=desc->getPointer();
1033   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1034   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1035     {
1036       if(!isImpacted[i])
1037         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1038       else
1039         {
1040           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1041             {
1042               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1043               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1044             }
1045           else
1046             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1047         }
1048     }
1049   revDesc->reserve(newNbOfCellsM1);
1050   revDescIndx->alloc(newNbOfCellsM1+1,1);
1051   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1052   const int *revDesc2Ptr=revDesc2->getConstPointer();
1053   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1054     {
1055       int oldCellIdM1=n2oM1Ptr[i];
1056       if(!isImpacted[oldCellIdM1])
1057         {
1058           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1059           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1060         }
1061       else
1062         {
1063           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1064             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1065           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1066           commonCellsIPtr++;
1067         }
1068     }
1069   //
1070   return ret2.retn();
1071 }
1072
1073 struct MEDCouplingAccVisit
1074 {
1075   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1076   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1077   int _new_nb_of_nodes;
1078 };
1079
1080 /// @endcond
1081
1082 /*!
1083  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1084  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1085  * array of cell ids. Pay attention that after conversion all algorithms work slower
1086  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1087  * conversion due presence of invalid ids in the array of cells to convert, as a
1088  * result \a this mesh contains some already converted elements. In this case the 2D
1089  * mesh remains valid but 3D mesh becomes \b inconsistent!
1090  *  \warning This method can significantly modify the order of geometric types in \a this,
1091  *          hence, to write this mesh to the MED file, its cells must be sorted using
1092  *          sortCellsInMEDFileFrmt().
1093  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1094  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1095  *         cellIdsToConvertBg.
1096  *  \throw If the coordinates array is not set.
1097  *  \throw If the nodal connectivity of cells is node defined.
1098  *  \throw If dimension of \a this mesh is not either 2 or 3.
1099  *
1100  *  \if ENABLE_EXAMPLES
1101  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1102  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1103  *  \endif
1104  */
1105 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1106 {
1107   checkFullyDefined();
1108   int dim=getMeshDimension();
1109   if(dim<2 || dim>3)
1110     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1111   int nbOfCells(getNumberOfCells());
1112   if(dim==2)
1113     {
1114       const int *connIndex=_nodal_connec_index->getConstPointer();
1115       int *conn=_nodal_connec->getPointer();
1116       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1117         {
1118           if(*iter>=0 && *iter<nbOfCells)
1119             {
1120               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1121               if(!cm.isQuadratic())
1122                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1123               else
1124                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1125             }
1126           else
1127             {
1128               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1129               oss << " in range [0," << nbOfCells << ") !";
1130               throw INTERP_KERNEL::Exception(oss.str().c_str());
1131             }
1132         }
1133     }
1134   else
1135     {
1136       int *connIndex(_nodal_connec_index->getPointer());
1137       const int *connOld(_nodal_connec->getConstPointer());
1138       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1139       std::vector<bool> toBeDone(nbOfCells,false);
1140       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1141         {
1142           if(*iter>=0 && *iter<nbOfCells)
1143             toBeDone[*iter]=true;
1144           else
1145             {
1146               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1147               oss << " in range [0," << nbOfCells << ") !";
1148               throw INTERP_KERNEL::Exception(oss.str().c_str());
1149             }
1150         }
1151       for(int cellId=0;cellId<nbOfCells;cellId++)
1152         {
1153           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1154           int lgthOld(posP1-pos-1);
1155           if(toBeDone[cellId])
1156             {
1157               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1158               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1159               int *tmp(new int[nbOfFaces*lgthOld+1]);
1160               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1161               for(unsigned j=0;j<nbOfFaces;j++)
1162                 {
1163                   INTERP_KERNEL::NormalizedCellType type;
1164                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1165                   work+=offset;
1166                   *work++=-1;
1167                 }
1168               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1169               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1170               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1171               delete [] tmp;
1172             }
1173           else
1174             {
1175               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1176               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1177             }
1178         }
1179       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1180     }
1181   computeTypes();
1182 }
1183
1184 /*!
1185  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1186  * polyhedrons (if \a this is a 3D mesh).
1187  *  \warning As this method is purely for user-friendliness and no optimization is
1188  *          done to avoid construction of a useless vector, this method can be costly
1189  *          in memory.
1190  *  \throw If the coordinates array is not set.
1191  *  \throw If the nodal connectivity of cells is node defined.
1192  *  \throw If dimension of \a this mesh is not either 2 or 3.
1193  */
1194 void MEDCouplingUMesh::convertAllToPoly()
1195 {
1196   int nbOfCells=getNumberOfCells();
1197   std::vector<int> cellIds(nbOfCells);
1198   for(int i=0;i<nbOfCells;i++)
1199     cellIds[i]=i;
1200   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1201 }
1202
1203 /*!
1204  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1205  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1206  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1207  * base facet of the volume and the second half of nodes describes an opposite facet
1208  * having the same number of nodes as the base one. This method converts such
1209  * connectivity to a valid polyhedral format where connectivity of each facet is
1210  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1211  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1212  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1213  * a correct orientation of the first facet of a polyhedron, else orientation of a
1214  * corrected cell is reverse.<br>
1215  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1216  * it releases the user from boring description of polyhedra connectivity in the valid
1217  * format.
1218  *  \throw If \a this->getMeshDimension() != 3.
1219  *  \throw If \a this->getSpaceDimension() != 3.
1220  *  \throw If the nodal connectivity of cells is not defined.
1221  *  \throw If the coordinates array is not set.
1222  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1223  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1224  *
1225  *  \if ENABLE_EXAMPLES
1226  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1227  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1228  *  \endif
1229  */
1230 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1231 {
1232   checkFullyDefined();
1233   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1234     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1235   int nbOfCells=getNumberOfCells();
1236   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1237   newCi->alloc(nbOfCells+1,1);
1238   int *newci=newCi->getPointer();
1239   const int *ci=_nodal_connec_index->getConstPointer();
1240   const int *c=_nodal_connec->getConstPointer();
1241   newci[0]=0;
1242   for(int i=0;i<nbOfCells;i++)
1243     {
1244       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1245       if(type==INTERP_KERNEL::NORM_POLYHED)
1246         {
1247           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1248             {
1249               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1250               throw INTERP_KERNEL::Exception(oss.str().c_str());
1251             }
1252           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1253           if(n2%2!=0)
1254             {
1255               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 !";
1256               throw INTERP_KERNEL::Exception(oss.str().c_str());
1257             }
1258           int n1=(int)(n2/2);
1259           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)
1260         }
1261       else
1262         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1263     }
1264   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1265   newC->alloc(newci[nbOfCells],1);
1266   int *newc=newC->getPointer();
1267   for(int i=0;i<nbOfCells;i++)
1268     {
1269       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1270       if(type==INTERP_KERNEL::NORM_POLYHED)
1271         {
1272           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1273           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1274           *newc++=-1;
1275           for(std::size_t j=0;j<n1;j++)
1276             {
1277               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1278               newc[n1+5*j]=-1;
1279               newc[n1+5*j+1]=c[ci[i]+1+j];
1280               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1281               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1282               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1283             }
1284           newc+=n1*6;
1285         }
1286       else
1287         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1288     }
1289   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1290   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1291 }
1292
1293
1294 /*!
1295  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1296  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1297  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1298  *          to write this mesh to the MED file, its cells must be sorted using
1299  *          sortCellsInMEDFileFrmt().
1300  * \return \c true if at least one cell has been converted, \c false else. In the
1301  *         last case the nodal connectivity remains unchanged.
1302  * \throw If the coordinates array is not set.
1303  * \throw If the nodal connectivity of cells is not defined.
1304  * \throw If \a this->getMeshDimension() < 0.
1305  */
1306 bool MEDCouplingUMesh::unPolyze()
1307 {
1308   checkFullyDefined();
1309   int mdim=getMeshDimension();
1310   if(mdim<0)
1311     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1312   if(mdim<=1)
1313     return false;
1314   int nbOfCells=getNumberOfCells();
1315   if(nbOfCells<1)
1316     return false;
1317   int initMeshLgth=getMeshLength();
1318   int *conn=_nodal_connec->getPointer();
1319   int *index=_nodal_connec_index->getPointer();
1320   int posOfCurCell=0;
1321   int newPos=0;
1322   int lgthOfCurCell;
1323   bool ret=false;
1324   for(int i=0;i<nbOfCells;i++)
1325     {
1326       lgthOfCurCell=index[i+1]-posOfCurCell;
1327       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1328       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1329       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1330       int newLgth;
1331       if(cm.isDynamic())
1332         {
1333           switch(cm.getDimension())
1334           {
1335             case 2:
1336               {
1337                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1338                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1339                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1340                 break;
1341               }
1342             case 3:
1343               {
1344                 int nbOfFaces,lgthOfPolyhConn;
1345                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1346                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1347                 break;
1348               }
1349             case 1:
1350               {
1351                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1352                 break;
1353               }
1354           }
1355           ret=ret || (newType!=type);
1356           conn[newPos]=newType;
1357           newPos+=newLgth+1;
1358           posOfCurCell=index[i+1];
1359           index[i+1]=newPos;
1360         }
1361       else
1362         {
1363           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1364           newPos+=lgthOfCurCell;
1365           posOfCurCell+=lgthOfCurCell;
1366           index[i+1]=newPos;
1367         }
1368     }
1369   if(newPos!=initMeshLgth)
1370     _nodal_connec->reAlloc(newPos);
1371   if(ret)
1372     computeTypes();
1373   return ret;
1374 }
1375
1376 /*!
1377  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1378  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1379  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1380  *
1381  * \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 
1382  *             precision.
1383  */
1384 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1385 {
1386   checkFullyDefined();
1387   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1388     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1389   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1390   coords->recenterForMaxPrecision(eps);
1391   //
1392   int nbOfCells=getNumberOfCells();
1393   const int *conn=_nodal_connec->getConstPointer();
1394   const int *index=_nodal_connec_index->getConstPointer();
1395   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1396   connINew->alloc(nbOfCells+1,1);
1397   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1399   bool changed=false;
1400   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1401     {
1402       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1403         {
1404           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1405           changed=true;
1406         }
1407       else
1408         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1409       *connINewPtr=connNew->getNumberOfTuples();
1410     }
1411   if(changed)
1412     setConnectivity(connNew,connINew,false);
1413 }
1414
1415 /*!
1416  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1417  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1418  * the format of the returned DataArrayInt instance.
1419  * 
1420  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1421  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1422  */
1423 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1424 {
1425   checkConnectivityFullyDefined();
1426   int nbOfCells=getNumberOfCells();
1427   const int *connIndex=_nodal_connec_index->getConstPointer();
1428   const int *conn=_nodal_connec->getConstPointer();
1429   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1430   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1431   std::vector<bool> retS(maxElt,false);
1432   for(int i=0;i<nbOfCells;i++)
1433     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1434       if(conn[j]>=0)
1435         retS[conn[j]]=true;
1436   int sz=0;
1437   for(int i=0;i<maxElt;i++)
1438     if(retS[i])
1439       sz++;
1440   DataArrayInt *ret=DataArrayInt::New();
1441   ret->alloc(sz,1);
1442   int *retPtr=ret->getPointer();
1443   for(int i=0;i<maxElt;i++)
1444     if(retS[i])
1445       *retPtr++=i;
1446   return ret;
1447 }
1448
1449 /*!
1450  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1451  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1452  */
1453 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1454 {
1455   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1456   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1457   for(int i=0;i<nbOfCells;i++)
1458     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1459       if(conn[j]>=0)
1460         {
1461           if(conn[j]<nbOfNodes)
1462             nodeIdsInUse[conn[j]]=true;
1463           else
1464             {
1465               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1466               throw INTERP_KERNEL::Exception(oss.str().c_str());
1467             }
1468         }
1469 }
1470
1471 /*!
1472  * Finds nodes not used in any cell and returns an array giving a new id to every node
1473  * by excluding the unused nodes, for which the array holds -1. The result array is
1474  * a mapping in "Old to New" mode. 
1475  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1476  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1477  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1478  *          if the node is unused or a new id else. The caller is to delete this
1479  *          array using decrRef() as it is no more needed.  
1480  *  \throw If the coordinates array is not set.
1481  *  \throw If the nodal connectivity of cells is not defined.
1482  *  \throw If the nodal connectivity includes an invalid id.
1483  *
1484  *  \if ENABLE_EXAMPLES
1485  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1486  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1487  *  \endif
1488  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1489  */
1490 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1491 {
1492   nbrOfNodesInUse=-1;
1493   int nbOfNodes(getNumberOfNodes());
1494   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1495   ret->alloc(nbOfNodes,1);
1496   int *traducer=ret->getPointer();
1497   std::fill(traducer,traducer+nbOfNodes,-1);
1498   int nbOfCells=getNumberOfCells();
1499   const int *connIndex=_nodal_connec_index->getConstPointer();
1500   const int *conn=_nodal_connec->getConstPointer();
1501   for(int i=0;i<nbOfCells;i++)
1502     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1503       if(conn[j]>=0)
1504         {
1505           if(conn[j]<nbOfNodes)
1506             traducer[conn[j]]=1;
1507           else
1508             {
1509               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1510               throw INTERP_KERNEL::Exception(oss.str().c_str());
1511             }
1512         }
1513   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1514   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1515   return ret.retn();
1516 }
1517
1518 /*!
1519  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1520  * For each cell in \b this the number of nodes constituting cell is computed.
1521  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1522  * So for pohyhedrons some nodes can be counted several times in the returned result.
1523  * 
1524  * \return a newly allocated array
1525  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1526  */
1527 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1528 {
1529   checkConnectivityFullyDefined();
1530   int nbOfCells=getNumberOfCells();
1531   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1532   ret->alloc(nbOfCells,1);
1533   int *retPtr=ret->getPointer();
1534   const int *conn=getNodalConnectivity()->getConstPointer();
1535   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1536   for(int i=0;i<nbOfCells;i++,retPtr++)
1537     {
1538       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1539         *retPtr=connI[i+1]-connI[i]-1;
1540       else
1541         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1542     }
1543   return ret.retn();
1544 }
1545
1546 /*!
1547  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1548  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1549  *
1550  * \return DataArrayInt * - new object to be deallocated by the caller.
1551  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1552  */
1553 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1554 {
1555   checkConnectivityFullyDefined();
1556   int nbOfCells=getNumberOfCells();
1557   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1558   ret->alloc(nbOfCells,1);
1559   int *retPtr=ret->getPointer();
1560   const int *conn=getNodalConnectivity()->getConstPointer();
1561   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1562   for(int i=0;i<nbOfCells;i++,retPtr++)
1563     {
1564       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1565       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1566         *retPtr=(int)s.size();
1567       else
1568         {
1569           s.erase(-1);
1570           *retPtr=(int)s.size();
1571         }
1572     }
1573   return ret.retn();
1574 }
1575
1576 /*!
1577  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1578  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1579  * 
1580  * \return a newly allocated array
1581  */
1582 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1583 {
1584   checkConnectivityFullyDefined();
1585   int nbOfCells=getNumberOfCells();
1586   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1587   ret->alloc(nbOfCells,1);
1588   int *retPtr=ret->getPointer();
1589   const int *conn=getNodalConnectivity()->getConstPointer();
1590   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1591   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1592     {
1593       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1594       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1595     }
1596   return ret.retn();
1597 }
1598
1599 /*!
1600  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1601  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1602  * array mean that the corresponding old node is no more used. 
1603  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1604  *           this->getNumberOfNodes() before call of this method. The caller is to
1605  *           delete this array using decrRef() as it is no more needed. 
1606  *  \throw If the coordinates array is not set.
1607  *  \throw If the nodal connectivity of cells is not defined.
1608  *  \throw If the nodal connectivity includes an invalid id.
1609  *  \sa areAllNodesFetched
1610  *
1611  *  \if ENABLE_EXAMPLES
1612  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1613  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1614  *  \endif
1615  */
1616 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1617 {
1618   return MEDCouplingPointSet::zipCoordsTraducer();
1619 }
1620
1621 /*!
1622  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1623  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1624  */
1625 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1626 {
1627   switch(compType)
1628   {
1629     case 0:
1630       return AreCellsEqual0(conn,connI,cell1,cell2);
1631     case 1:
1632       return AreCellsEqual1(conn,connI,cell1,cell2);
1633     case 2:
1634       return AreCellsEqual2(conn,connI,cell1,cell2);
1635     case 3:
1636       return AreCellsEqual3(conn,connI,cell1,cell2);
1637     case 7:
1638       return AreCellsEqual7(conn,connI,cell1,cell2);
1639   }
1640   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1641 }
1642
1643 /*!
1644  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1645  */
1646 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1647 {
1648   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1649     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1650   return 0;
1651 }
1652
1653 /*!
1654  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1655  */
1656 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1657 {
1658   int sz=connI[cell1+1]-connI[cell1];
1659   if(sz==connI[cell2+1]-connI[cell2])
1660     {
1661       if(conn[connI[cell1]]==conn[connI[cell2]])
1662         {
1663           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1664           unsigned dim=cm.getDimension();
1665           if(dim!=3)
1666             {
1667               if(dim!=1)
1668                 {
1669                   int sz1=2*(sz-1);
1670                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1671                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1672                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1673                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1674                   return work!=tmp+sz1?1:0;
1675                 }
1676               else
1677                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1678             }
1679           else
1680             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1681         }
1682     }
1683   return 0;
1684 }
1685
1686 /*!
1687  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1688  */
1689 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1690 {
1691   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1692     {
1693       if(conn[connI[cell1]]==conn[connI[cell2]])
1694         {
1695           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1696           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1697           return s1==s2?1:0;
1698         }
1699     }
1700   return 0;
1701 }
1702
1703 /*!
1704  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1705  */
1706 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1707 {
1708   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1709     {
1710       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1711       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1712       return s1==s2?1:0;
1713     }
1714   return 0;
1715 }
1716
1717 /*!
1718  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1719  */
1720 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1721 {
1722   int sz=connI[cell1+1]-connI[cell1];
1723   if(sz==connI[cell2+1]-connI[cell2])
1724     {
1725       if(conn[connI[cell1]]==conn[connI[cell2]])
1726         {
1727           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1728           unsigned dim=cm.getDimension();
1729           if(dim!=3)
1730             {
1731               if(dim!=1)
1732                 {
1733                   int sz1=2*(sz-1);
1734                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1735                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1736                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1737                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1738                   if(work!=tmp+sz1)
1739                     return 1;
1740                   else
1741                     {
1742                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1743                       std::reverse_iterator<int *> it2((int *)tmp);
1744                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1745                         return 2;
1746                       else
1747                         return 0;
1748                     }
1749
1750                   return work!=tmp+sz1?1:0;
1751                 }
1752               else
1753                 {//case of SEG2 and SEG3
1754                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1755                     return 1;
1756                   if(!cm.isQuadratic())
1757                     {
1758                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1759                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1760                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1761                         return 2;
1762                       return 0;
1763                     }
1764                   else
1765                     {
1766                       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])
1767                         return 2;
1768                       return 0;
1769                     }
1770                 }
1771             }
1772           else
1773             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1774         }
1775     }
1776   return 0;
1777 }
1778
1779 /*!
1780  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1781  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1782  * and result remains unchanged.
1783  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1784  * If in 'candidates' pool -1 value is considered as an empty value.
1785  * WARNING this method returns only ONE set of result !
1786  */
1787 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1788 {
1789   if(candidates.size()<1)
1790     return false;
1791   bool ret=false;
1792   std::vector<int>::const_iterator iter=candidates.begin();
1793   int start=(*iter++);
1794   for(;iter!=candidates.end();iter++)
1795     {
1796       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1797       if(status!=0)
1798         {
1799           if(!ret)
1800             {
1801               result->pushBackSilent(start);
1802               ret=true;
1803             }
1804           if(status==1)
1805             result->pushBackSilent(*iter);
1806           else
1807             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1808         }
1809     }
1810   return ret;
1811 }
1812
1813 /*!
1814  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1815  * by \a compType.
1816  * This method keeps the coordiantes of \a this. This method is time consuming.
1817  *
1818  * \param [in] compType input specifying the technique used to compare cells each other.
1819  *   - 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.
1820  *   - 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)
1821  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1822  *   - 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
1823  * can be used for users not sensitive to orientation of cell
1824  * \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.
1825  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1826  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1827  * \return the correspondance array old to new in a newly allocated array.
1828  * 
1829  */
1830 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1831 {
1832   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1833   getReverseNodalConnectivity(revNodal,revNodalI);
1834   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1835 }
1836
1837 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1838                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1839 {
1840   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1841   int nbOfCells=nodalI->getNumberOfTuples()-1;
1842   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1843   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1844   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1845   std::vector<bool> isFetched(nbOfCells,false);
1846   if(startCellId==0)
1847     {
1848       for(int i=0;i<nbOfCells;i++)
1849         {
1850           if(!isFetched[i])
1851             {
1852               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1853               std::vector<int> v,v2;
1854               if(connOfNode!=connPtr+connIPtr[i+1])
1855                 {
1856                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1857                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1858                   connOfNode++;
1859                 }
1860               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1861                 if(*connOfNode>=0)
1862                   {
1863                     v=v2;
1864                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1865                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1866                     v2.resize(std::distance(v2.begin(),it));
1867                   }
1868               if(v2.size()>1)
1869                 {
1870                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1871                     {
1872                       int pos=commonCellsI->back();
1873                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1874                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1875                         isFetched[*it]=true;
1876                     }
1877                 }
1878             }
1879         }
1880     }
1881   else
1882     {
1883       for(int i=startCellId;i<nbOfCells;i++)
1884         {
1885           if(!isFetched[i])
1886             {
1887               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1888               std::vector<int> v,v2;
1889               if(connOfNode!=connPtr+connIPtr[i+1])
1890                 {
1891                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1892                   connOfNode++;
1893                 }
1894               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1895                 if(*connOfNode>=0)
1896                   {
1897                     v=v2;
1898                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1899                     v2.resize(std::distance(v2.begin(),it));
1900                   }
1901               if(v2.size()>1)
1902                 {
1903                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1904                     {
1905                       int pos=commonCellsI->back();
1906                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1907                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1908                         isFetched[*it]=true;
1909                     }
1910                 }
1911             }
1912         }
1913     }
1914   commonCellsArr=commonCells.retn();
1915   commonCellsIArr=commonCellsI.retn();
1916 }
1917
1918 /*!
1919  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1920  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1921  * than \a other->getNumberOfCells() in the returned array means that there is no
1922  * corresponding cell in \a this mesh.
1923  * It is expected that \a this and \a other meshes share the same node coordinates
1924  * array, if it is not so an exception is thrown. 
1925  *  \param [in] other - the mesh to compare with.
1926  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1927  *         valid values [0,1,2], see zipConnectivityTraducer().
1928  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1929  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1930  *         values. The caller is to delete this array using
1931  *         decrRef() as it is no more needed.
1932  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1933  *         mesh.
1934  *
1935  *  \if ENABLE_EXAMPLES
1936  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1937  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1938  *  \endif
1939  *  \sa checkDeepEquivalOnSameNodesWith()
1940  *  \sa checkGeoEquivalWith()
1941  */
1942 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1943 {
1944   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1945   int nbOfCells=getNumberOfCells();
1946   static const int possibleCompType[]={0,1,2};
1947   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1948     {
1949       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1950       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1951       oss << " !";
1952       throw INTERP_KERNEL::Exception(oss.str().c_str());
1953     }
1954   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1955   arr=o2n->substr(nbOfCells);
1956   arr->setName(other->getName());
1957   int tmp;
1958   if(other->getNumberOfCells()==0)
1959     return true;
1960   return arr->getMaxValue(tmp)<nbOfCells;
1961 }
1962
1963 /*!
1964  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1965  * This method tries to determine if \b other is fully included in \b this.
1966  * The main difference is that this method is not expected to throw exception.
1967  * This method has two outputs :
1968  *
1969  * \param other other mesh
1970  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1971  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1972  */
1973 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1974 {
1975   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1976   DataArrayInt *commonCells=0,*commonCellsI=0;
1977   int thisNbCells=getNumberOfCells();
1978   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1979   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1980   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1981   int otherNbCells=other->getNumberOfCells();
1982   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1983   arr2->alloc(otherNbCells,1);
1984   arr2->fillWithZero();
1985   int *arr2Ptr=arr2->getPointer();
1986   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1987   for(int i=0;i<nbOfCommon;i++)
1988     {
1989       int start=commonCellsPtr[commonCellsIPtr[i]];
1990       if(start<thisNbCells)
1991         {
1992           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1993             {
1994               int sig=commonCellsPtr[j]>0?1:-1;
1995               int val=std::abs(commonCellsPtr[j])-1;
1996               if(val>=thisNbCells)
1997                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1998             }
1999         }
2000     }
2001   arr2->setName(other->getName());
2002   if(arr2->presenceOfValue(0))
2003     return false;
2004   arr=arr2.retn();
2005   return true;
2006 }
2007
2008 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
2009 {
2010   if(!other)
2011     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
2012   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
2013   if(!otherC)
2014     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
2015   std::vector<const MEDCouplingUMesh *> ms(2);
2016   ms[0]=this;
2017   ms[1]=otherC;
2018   return MergeUMeshesOnSameCoords(ms);
2019 }
2020
2021 /*!
2022  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2023  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2024  * cellIds is not given explicitely but by a range python like.
2025  * 
2026  * \param start
2027  * \param end
2028  * \param step
2029  * \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.
2030  * \return a newly allocated
2031  * 
2032  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2033  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2034  */
2035 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2036 {
2037   if(getMeshDimension()!=-1)
2038     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2039   else
2040     {
2041       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2042       if(newNbOfCells!=1)
2043         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2044       if(start!=0)
2045         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2046       incrRef();
2047       return const_cast<MEDCouplingUMesh *>(this);
2048     }
2049 }
2050
2051 /*!
2052  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2053  * The result mesh shares or not the node coordinates array with \a this mesh depending
2054  * on \a keepCoords parameter.
2055  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2056  *           to write this mesh to the MED file, its cells must be sorted using
2057  *           sortCellsInMEDFileFrmt().
2058  *  \param [in] begin - an array of cell ids to include to the new mesh.
2059  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2060  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2061  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2062  *         by calling zipCoords().
2063  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2064  *         to delete this mesh using decrRef() as it is no more needed. 
2065  *  \throw If the coordinates array is not set.
2066  *  \throw If the nodal connectivity of cells is not defined.
2067  *  \throw If any cell id in the array \a begin is not valid.
2068  *
2069  *  \if ENABLE_EXAMPLES
2070  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2071  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2072  *  \endif
2073  */
2074 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2075 {
2076   if(getMeshDimension()!=-1)
2077     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2078   else
2079     {
2080       if(end-begin!=1)
2081         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2082       if(begin[0]!=0)
2083         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2084       incrRef();
2085       return const_cast<MEDCouplingUMesh *>(this);
2086     }
2087 }
2088
2089 /*!
2090  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2091  *
2092  * 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.
2093  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2094  * The number of cells of \b this will remain the same with this method.
2095  *
2096  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2097  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2098  * \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 ).
2099  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2100  */
2101 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2102 {
2103   checkConnectivityFullyDefined();
2104   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2105   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2106     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2107   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2108     {
2109       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2110       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2111       throw INTERP_KERNEL::Exception(oss.str().c_str());
2112     }
2113   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2114   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2115     {
2116       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2117       throw INTERP_KERNEL::Exception(oss.str().c_str());
2118     }
2119   int nbOfCells=getNumberOfCells();
2120   bool easyAssign=true;
2121   const int *connI=_nodal_connec_index->getConstPointer();
2122   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2123   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2124     {
2125       if(*it>=0 && *it<nbOfCells)
2126         {
2127           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2128         }
2129       else
2130         {
2131           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2132           throw INTERP_KERNEL::Exception(oss.str().c_str());
2133         }
2134     }
2135   if(easyAssign)
2136     {
2137       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2138       computeTypes();
2139     }
2140   else
2141     {
2142       DataArrayInt *arrOut=0,*arrIOut=0;
2143       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2144                                                arrOut,arrIOut);
2145       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2146       setConnectivity(arrOut,arrIOut,true);
2147     }
2148 }
2149
2150 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2151 {
2152   checkConnectivityFullyDefined();
2153   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2154   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2155     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2156   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2157     {
2158       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2159       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2160       throw INTERP_KERNEL::Exception(oss.str().c_str());
2161     }
2162   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2163   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2164     {
2165       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2166       throw INTERP_KERNEL::Exception(oss.str().c_str());
2167     }
2168   int nbOfCells=getNumberOfCells();
2169   bool easyAssign=true;
2170   const int *connI=_nodal_connec_index->getConstPointer();
2171   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2172   int it=start;
2173   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2174     {
2175       if(it>=0 && it<nbOfCells)
2176         {
2177           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2178         }
2179       else
2180         {
2181           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2182           throw INTERP_KERNEL::Exception(oss.str().c_str());
2183         }
2184     }
2185   if(easyAssign)
2186     {
2187       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2188       computeTypes();
2189     }
2190   else
2191     {
2192       DataArrayInt *arrOut=0,*arrIOut=0;
2193       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2194                                                 arrOut,arrIOut);
2195       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2196       setConnectivity(arrOut,arrIOut,true);
2197     }
2198 }                      
2199
2200 /*!
2201  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2202  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2203  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2204  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2205  *
2206  * \param [in] begin input start of array of node ids.
2207  * \param [in] end input end of array of node ids.
2208  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2209  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2210  */
2211 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2212 {
2213   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2214   checkConnectivityFullyDefined();
2215   int tmp=-1;
2216   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2217   std::vector<bool> fastFinder(sz,false);
2218   for(const int *work=begin;work!=end;work++)
2219     if(*work>=0 && *work<sz)
2220       fastFinder[*work]=true;
2221   int nbOfCells=getNumberOfCells();
2222   const int *conn=getNodalConnectivity()->getConstPointer();
2223   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2224   for(int i=0;i<nbOfCells;i++)
2225     {
2226       int ref=0,nbOfHit=0;
2227       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2228         if(*work2>=0)
2229           {
2230             ref++;
2231             if(fastFinder[*work2])
2232               nbOfHit++;
2233           }
2234       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2235         cellIdsKept->pushBackSilent(i);
2236     }
2237   cellIdsKeptArr=cellIdsKept.retn();
2238 }
2239
2240 /*!
2241  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2242  * this->getMeshDimension(), that bound some cells of \a this mesh.
2243  * The cells of lower dimension to include to the result mesh are selected basing on
2244  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2245  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2246  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2247  * created mesh shares the node coordinates array with \a this mesh. 
2248  *  \param [in] begin - the array of node ids.
2249  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2250  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2251  *         array \a begin are added, else cells whose any node is in the
2252  *         array \a begin are added.
2253  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2254  *         to delete this mesh using decrRef() as it is no more needed. 
2255  *  \throw If the coordinates array is not set.
2256  *  \throw If the nodal connectivity of cells is not defined.
2257  *  \throw If any node id in \a begin is not valid.
2258  *
2259  *  \if ENABLE_EXAMPLES
2260  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2261  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2262  *  \endif
2263  */
2264 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2265 {
2266   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2267   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2268   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2269   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2270   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2271 }
2272
2273 /*!
2274  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2275  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2276  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2277  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2278  *         by calling zipCoords().
2279  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2280  *         to delete this mesh using decrRef() as it is no more needed. 
2281  *  \throw If the coordinates array is not set.
2282  *  \throw If the nodal connectivity of cells is not defined.
2283  *
2284  *  \if ENABLE_EXAMPLES
2285  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2286  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2287  *  \endif
2288  */
2289 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2290 {
2291   DataArrayInt *desc=DataArrayInt::New();
2292   DataArrayInt *descIndx=DataArrayInt::New();
2293   DataArrayInt *revDesc=DataArrayInt::New();
2294   DataArrayInt *revDescIndx=DataArrayInt::New();
2295   //
2296   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2297   revDesc->decrRef();
2298   desc->decrRef();
2299   descIndx->decrRef();
2300   int nbOfCells=meshDM1->getNumberOfCells();
2301   const int *revDescIndxC=revDescIndx->getConstPointer();
2302   std::vector<int> boundaryCells;
2303   for(int i=0;i<nbOfCells;i++)
2304     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2305       boundaryCells.push_back(i);
2306   revDescIndx->decrRef();
2307   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2308   return ret;
2309 }
2310
2311 /*!
2312  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2313  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2314  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2315  */
2316 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2317 {
2318   checkFullyDefined();
2319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2321   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2323   //
2324   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2325   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2326   //
2327   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2328   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2329   const int *revDescPtr=revDesc->getConstPointer();
2330   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2331   int nbOfCells=getNumberOfCells();
2332   std::vector<bool> ret1(nbOfCells,false);
2333   int sz=0;
2334   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2335     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2336       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2337   //
2338   DataArrayInt *ret2=DataArrayInt::New();
2339   ret2->alloc(sz,1);
2340   int *ret2Ptr=ret2->getPointer();
2341   sz=0;
2342   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2343     if(*it)
2344       *ret2Ptr++=sz;
2345   ret2->setName("BoundaryCells");
2346   return ret2;
2347 }
2348
2349 /*!
2350  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2351  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2352  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2353  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2354  *
2355  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2356  * 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
2357  * equals a cell in \b otherDimM1OnSameCoords.
2358  *
2359  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2360  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2361  *
2362  * \param [in] otherDimM1OnSameCoords
2363  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2364  * \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
2365  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2366  */
2367 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2368 {
2369   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2370     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2371   checkConnectivityFullyDefined();
2372   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2373   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2374     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2375   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2377   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2378   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2379   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2380   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2381   DataArrayInt *idsOtherInConsti=0;
2382   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2384   if(!b)
2385     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2386   std::set<int> s1;
2387   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2388     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2390   s1arr_renum1->sort();
2391   cellIdsRk0=s0arr.retn();
2392   //cellIdsRk1=s_renum1.retn();
2393   cellIdsRk1=s1arr_renum1.retn();
2394 }
2395
2396 /*!
2397  * 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
2398  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2399  * 
2400  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2401  */
2402 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2403 {
2404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2406   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2407   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2408   //
2409   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2410   revDesc=0; desc=0; descIndx=0;
2411   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2413   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2414 }
2415
2416 /*!
2417  * Finds nodes lying on the boundary of \a this mesh.
2418  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2419  *          nodes. The caller is to delete this array using decrRef() as it is no
2420  *          more needed.
2421  *  \throw If the coordinates array is not set.
2422  *  \throw If the nodal connectivity of cells is node defined.
2423  *
2424  *  \if ENABLE_EXAMPLES
2425  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2426  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2427  *  \endif
2428  */
2429 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2430 {
2431   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2432   return skin->computeFetchedNodeIds();
2433 }
2434
2435 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2436 {
2437   incrRef();
2438   return const_cast<MEDCouplingUMesh *>(this);
2439 }
2440
2441 /*!
2442  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2443  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2444  * 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.
2445  * 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.
2446  * 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.
2447  *
2448  * \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
2449  *             parameter is altered during the call.
2450  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2451  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2452  * \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.
2453  *
2454  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2455  */
2456 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2457                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2458 {
2459   typedef MEDCouplingAutoRefCountObjectPtr<DataArrayInt> DAInt;
2460
2461   checkFullyDefined();
2462   otherDimM1OnSameCoords.checkFullyDefined();
2463   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2464     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2465   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2466     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2467   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2468   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2469   DAInt cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2470   DAInt s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2471   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2472   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2473   DAInt s1=m0Part->computeFetchedNodeIds();
2474   DAInt s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2475   DAInt s3=s2->buildSubstraction(s1);
2476   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2477   //
2478   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2479   int nCells2 = m0Part2->getNumberOfCells();
2480   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2481   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2482   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2483   DataArrayInt *tmp00=0,*tmp11=0;
2484   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2485   DAInt neighInit00(tmp00);
2486   DAInt neighIInit00(tmp11);
2487   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2488   DataArrayInt *idsTmp=0;
2489   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2490   DAInt ids(idsTmp);
2491   if(!b)
2492     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2493   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2494   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2495   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2496   DataArrayInt *tmp0=0,*tmp1=0;
2497   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2498   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2499   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2500   DAInt neigh00(tmp0);
2501   DAInt neighI00(tmp1);
2502
2503   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2504   int seed = 0, nIter = 0;
2505   int nIterMax = nCells2+1; // Safety net for the loop
2506   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2507   hitCells->fillWithValue(-1);
2508   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2509   cellsToModifyConn0_torenum->alloc(0,1);
2510   while (nIter < nIterMax)
2511     {
2512       DAInt t = hitCells->getIdsEqual(-1);
2513       if (!t->getNumberOfTuples())
2514         break;
2515       // Connex zone without the crack (to compute the next seed really)
2516       int dnu;
2517       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2518       int cnt = 0;
2519       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2520         hitCells->setIJ(*ptr,0,1);
2521       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2522       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2523       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2524       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2525       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2526       DAInt nonHitCells = hitCells->getIdsEqual(-1);
2527       DAInt intersec = nonHitCells->buildIntersection(comple);
2528       if (intersec->getNumberOfTuples())
2529         { seed = intersec->getIJ(0,0); }
2530       else
2531         { break; }
2532       nIter++;
2533     }
2534   if (nIter >= nIterMax)
2535     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2536
2537   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2538   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2539   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2540   //
2541   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2542   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2543   nodeIdsToDuplicate=s3.retn();
2544 }
2545
2546 /*!
2547  * This method operates a modification of the connectivity and coords in \b this.
2548  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2549  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2550  * 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
2551  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2552  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2553  * 
2554  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2555  * 
2556  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2557  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2558  */
2559 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2560 {
2561   int nbOfNodes=getNumberOfNodes();
2562   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2563   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2564 }
2565
2566 /*!
2567  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2568  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2569  *
2570  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2571  *
2572  * \sa renumberNodesInConn
2573  */
2574 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2575 {
2576   checkConnectivityFullyDefined();
2577   int *conn(getNodalConnectivity()->getPointer());
2578   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2579   int nbOfCells(getNumberOfCells());
2580   for(int i=0;i<nbOfCells;i++)
2581     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2582       {
2583         int& node=conn[iconn];
2584         if(node>=0)//avoid polyhedron separator
2585           {
2586             node+=offset;
2587           }
2588       }
2589   _nodal_connec->declareAsNew();
2590   updateTime();
2591 }
2592
2593 /*!
2594  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2595  *  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
2596  *  of a big mesh.
2597  */
2598 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2599 {
2600   checkConnectivityFullyDefined();
2601   int *conn(getNodalConnectivity()->getPointer());
2602   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2603   int nbOfCells(getNumberOfCells());
2604   for(int i=0;i<nbOfCells;i++)
2605     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2606       {
2607         int& node=conn[iconn];
2608         if(node>=0)//avoid polyhedron separator
2609           {
2610             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2611             if(it!=newNodeNumbersO2N.end())
2612               {
2613                 node=(*it).second;
2614               }
2615             else
2616               {
2617                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2618                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2619               }
2620           }
2621       }
2622   _nodal_connec->declareAsNew();
2623   updateTime();
2624 }
2625
2626 /*!
2627  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2628  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2629  * This method is a generalization of shiftNodeNumbersInConn().
2630  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2631  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2632  *         this->getNumberOfNodes(), in "Old to New" mode. 
2633  *         See \ref numbering for more info on renumbering modes.
2634  *  \throw If the nodal connectivity of cells is not defined.
2635  *
2636  *  \if ENABLE_EXAMPLES
2637  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2638  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2639  *  \endif
2640  */
2641 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2642 {
2643   checkConnectivityFullyDefined();
2644   int *conn=getNodalConnectivity()->getPointer();
2645   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2646   int nbOfCells(getNumberOfCells());
2647   for(int i=0;i<nbOfCells;i++)
2648     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2649       {
2650         int& node=conn[iconn];
2651         if(node>=0)//avoid polyhedron separator
2652           {
2653             node=newNodeNumbersO2N[node];
2654           }
2655       }
2656   _nodal_connec->declareAsNew();
2657   updateTime();
2658 }
2659
2660 /*!
2661  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2662  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2663  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2664  * 
2665  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2666  */
2667 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2668 {
2669   checkConnectivityFullyDefined();
2670   int *conn=getNodalConnectivity()->getPointer();
2671   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2672   int nbOfCells=getNumberOfCells();
2673   for(int i=0;i<nbOfCells;i++)
2674     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2675       {
2676         int& node=conn[iconn];
2677         if(node>=0)//avoid polyhedron separator
2678           {
2679             node+=delta;
2680           }
2681       }
2682   _nodal_connec->declareAsNew();
2683   updateTime();
2684 }
2685
2686 /*!
2687  * This method operates a modification of the connectivity in \b this.
2688  * 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.
2689  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2690  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2691  * 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
2692  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2693  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2694  * 
2695  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2696  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2697  * 
2698  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2699  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2700  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2701  */
2702 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2703 {
2704   checkConnectivityFullyDefined();
2705   std::map<int,int> m;
2706   int val=offset;
2707   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2708     m[*work]=val;
2709   int *conn=getNodalConnectivity()->getPointer();
2710   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2711   int nbOfCells=getNumberOfCells();
2712   for(int i=0;i<nbOfCells;i++)
2713     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2714       {
2715         int& node=conn[iconn];
2716         if(node>=0)//avoid polyhedron separator
2717           {
2718             std::map<int,int>::iterator it=m.find(node);
2719             if(it!=m.end())
2720               node=(*it).second;
2721           }
2722       }
2723   updateTime();
2724 }
2725
2726 /*!
2727  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2728  *
2729  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2730  * After the call of this method the number of cells remains the same as before.
2731  *
2732  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2733  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2734  * be strictly in [0;this->getNumberOfCells()).
2735  *
2736  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2737  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2738  * should be contained in[0;this->getNumberOfCells()).
2739  * 
2740  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2741  * \param check
2742  */
2743 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2744 {
2745   checkConnectivityFullyDefined();
2746   int nbCells=getNumberOfCells();
2747   const int *array=old2NewBg;
2748   if(check)
2749     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2750   //
2751   const int *conn=_nodal_connec->getConstPointer();
2752   const int *connI=_nodal_connec_index->getConstPointer();
2753   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2754   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2755   const int *n2oPtr=n2o->begin();
2756   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2757   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2758   newConn->copyStringInfoFrom(*_nodal_connec);
2759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2760   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2761   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2762   //
2763   int *newC=newConn->getPointer();
2764   int *newCI=newConnI->getPointer();
2765   int loc=0;
2766   newCI[0]=loc;
2767   for(int i=0;i<nbCells;i++)
2768     {
2769       int pos=n2oPtr[i];
2770       int nbOfElts=connI[pos+1]-connI[pos];
2771       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2772       loc+=nbOfElts;
2773       newCI[i+1]=loc;
2774     }
2775   //
2776   setConnectivity(newConn,newConnI);
2777   if(check)
2778     free(const_cast<int *>(array));
2779 }
2780
2781 /*!
2782  * Finds cells whose bounding boxes intersect a given bounding box.
2783  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2784  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2785  *         zMax (if in 3D). 
2786  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2787  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2788  *         extent of the bounding box of cell to produce an addition to this bounding box.
2789  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2790  *         cells. The caller is to delete this array using decrRef() as it is no more
2791  *         needed. 
2792  *  \throw If the coordinates array is not set.
2793  *  \throw If the nodal connectivity of cells is not defined.
2794  *
2795  *  \if ENABLE_EXAMPLES
2796  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2797  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2798  *  \endif
2799  */
2800 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2801 {
2802   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2803   if(getMeshDimension()==-1)
2804     {
2805       elems->pushBackSilent(0);
2806       return elems.retn();
2807     }
2808   int dim=getSpaceDimension();
2809   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2810   const int* conn      = getNodalConnectivity()->getConstPointer();
2811   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2812   const double* coords = getCoords()->getConstPointer();
2813   int nbOfCells=getNumberOfCells();
2814   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2815     {
2816       for (int i=0; i<dim; i++)
2817         {
2818           elem_bb[i*2]=std::numeric_limits<double>::max();
2819           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2820         }
2821
2822       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2823         {
2824           int node= conn[inode];
2825           if(node>=0)//avoid polyhedron separator
2826             {
2827               for (int idim=0; idim<dim; idim++)
2828                 {
2829                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2830                     {
2831                       elem_bb[idim*2] = coords[node*dim+idim] ;
2832                     }
2833                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2834                     {
2835                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2836                     }
2837                 }
2838             }
2839         }
2840       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2841         elems->pushBackSilent(ielem);
2842     }
2843   return elems.retn();
2844 }
2845
2846 /*!
2847  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2848  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2849  * added in 'elems' parameter.
2850  */
2851 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2852 {
2853   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2854   if(getMeshDimension()==-1)
2855     {
2856       elems->pushBackSilent(0);
2857       return elems.retn();
2858     }
2859   int dim=getSpaceDimension();
2860   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2861   const int* conn      = getNodalConnectivity()->getConstPointer();
2862   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2863   const double* coords = getCoords()->getConstPointer();
2864   int nbOfCells=getNumberOfCells();
2865   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2866     {
2867       for (int i=0; i<dim; i++)
2868         {
2869           elem_bb[i*2]=std::numeric_limits<double>::max();
2870           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2871         }
2872
2873       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2874         {
2875           int node= conn[inode];
2876           if(node>=0)//avoid polyhedron separator
2877             {
2878               for (int idim=0; idim<dim; idim++)
2879                 {
2880                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2881                     {
2882                       elem_bb[idim*2] = coords[node*dim+idim] ;
2883                     }
2884                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2885                     {
2886                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2887                     }
2888                 }
2889             }
2890         }
2891       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2892         elems->pushBackSilent(ielem);
2893     }
2894   return elems.retn();
2895 }
2896
2897 /*!
2898  * Returns a type of a cell by its id.
2899  *  \param [in] cellId - the id of the cell of interest.
2900  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2901  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2902  */
2903 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2904 {
2905   const int *ptI=_nodal_connec_index->getConstPointer();
2906   const int *pt=_nodal_connec->getConstPointer();
2907   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2908     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2909   else
2910     {
2911       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2912       throw INTERP_KERNEL::Exception(oss.str().c_str());
2913     }
2914 }
2915
2916 /*!
2917  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2918  * This method does not throw exception if geometric type \a type is not in \a this.
2919  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2920  * The coordinates array is not considered here.
2921  *
2922  * \param [in] type the geometric type
2923  * \return cell ids in this having geometric type \a type.
2924  */
2925 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2926 {
2927
2928   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2929   ret->alloc(0,1);
2930   checkConnectivityFullyDefined();
2931   int nbCells=getNumberOfCells();
2932   int mdim=getMeshDimension();
2933   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2934   if(mdim!=(int)cm.getDimension())
2935     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2936   const int *ptI=_nodal_connec_index->getConstPointer();
2937   const int *pt=_nodal_connec->getConstPointer();
2938   for(int i=0;i<nbCells;i++)
2939     {
2940       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2941         ret->pushBackSilent(i);
2942     }
2943   return ret.retn();
2944 }
2945
2946 /*!
2947  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2948  */
2949 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2950 {
2951   const int *ptI=_nodal_connec_index->getConstPointer();
2952   const int *pt=_nodal_connec->getConstPointer();
2953   int nbOfCells=getNumberOfCells();
2954   int ret=0;
2955   for(int i=0;i<nbOfCells;i++)
2956     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2957       ret++;
2958   return ret;
2959 }
2960
2961 /*!
2962  * Returns the nodal connectivity of a given cell.
2963  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2964  * all returned node ids can be used in getCoordinatesOfNode().
2965  *  \param [in] cellId - an id of the cell of interest.
2966  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2967  *         cleared before the appending.
2968  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2969  */
2970 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2971 {
2972   const int *ptI=_nodal_connec_index->getConstPointer();
2973   const int *pt=_nodal_connec->getConstPointer();
2974   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2975     if(*w>=0)
2976       conn.push_back(*w);
2977 }
2978
2979 std::string MEDCouplingUMesh::simpleRepr() const
2980 {
2981   static const char msg0[]="No coordinates specified !";
2982   std::ostringstream ret;
2983   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2984   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2985   int tmpp1,tmpp2;
2986   double tt=getTime(tmpp1,tmpp2);
2987   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2988   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2989   if(_mesh_dim>=-1)
2990     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2991   else
2992     { ret << " Mesh dimension has not been set or is invalid !"; }
2993   if(_coords!=0)
2994     {
2995       const int spaceDim=getSpaceDimension();
2996       ret << spaceDim << "\nInfo attached on space dimension : ";
2997       for(int i=0;i<spaceDim;i++)
2998         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2999       ret << "\n";
3000     }
3001   else
3002     ret << msg0 << "\n";
3003   ret << "Number of nodes : ";
3004   if(_coords!=0)
3005     ret << getNumberOfNodes() << "\n";
3006   else
3007     ret << msg0 << "\n";
3008   ret << "Number of cells : ";
3009   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3010     ret << getNumberOfCells() << "\n";
3011   else
3012     ret << "No connectivity specified !" << "\n";
3013   ret << "Cell types present : ";
3014   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3015     {
3016       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3017       ret << cm.getRepr() << " ";
3018     }
3019   ret << "\n";
3020   return ret.str();
3021 }
3022
3023 std::string MEDCouplingUMesh::advancedRepr() const
3024 {
3025   std::ostringstream ret;
3026   ret << simpleRepr();
3027   ret << "\nCoordinates array : \n___________________\n\n";
3028   if(_coords)
3029     _coords->reprWithoutNameStream(ret);
3030   else
3031     ret << "No array set !\n";
3032   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3033   reprConnectivityOfThisLL(ret);
3034   return ret.str();
3035 }
3036
3037 /*!
3038  * This method returns a C++ code that is a dump of \a this.
3039  * This method will throw if this is not fully defined.
3040  */
3041 std::string MEDCouplingUMesh::cppRepr() const
3042 {
3043   static const char coordsName[]="coords";
3044   static const char connName[]="conn";
3045   static const char connIName[]="connI";
3046   checkFullyDefined();
3047   std::ostringstream ret; ret << "// coordinates" << std::endl;
3048   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3049   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3050   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3051   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3052   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3053   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3054   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3055   return ret.str();
3056 }
3057
3058 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3059 {
3060   std::ostringstream ret;
3061   reprConnectivityOfThisLL(ret);
3062   return ret.str();
3063 }
3064
3065 /*!
3066  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3067  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3068  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3069  * some algos).
3070  * 
3071  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3072  * 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
3073  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3074  */
3075 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3076 {
3077   int mdim=getMeshDimension();
3078   if(mdim<0)
3079     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3080   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3081   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3082   bool needToCpyCT=true;
3083   if(!_nodal_connec)
3084     {
3085       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3086       needToCpyCT=false;
3087     }
3088   else
3089     {
3090       tmp1=_nodal_connec;
3091       tmp1->incrRef();
3092     }
3093   if(!_nodal_connec_index)
3094     {
3095       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3096       needToCpyCT=false;
3097     }
3098   else
3099     {
3100       tmp2=_nodal_connec_index;
3101       tmp2->incrRef();
3102     }
3103   ret->setConnectivity(tmp1,tmp2,false);
3104   if(needToCpyCT)
3105     ret->_types=_types;
3106   if(!_coords)
3107     {
3108       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3109       ret->setCoords(coords);
3110     }
3111   else
3112     ret->setCoords(_coords);
3113   return ret.retn();
3114 }
3115
3116 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3117 {
3118   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3119     {
3120       int nbOfCells=getNumberOfCells();
3121       const int *c=_nodal_connec->getConstPointer();
3122       const int *ci=_nodal_connec_index->getConstPointer();
3123       for(int i=0;i<nbOfCells;i++)
3124         {
3125           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3126           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3127           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3128           stream << "\n";
3129         }
3130     }
3131   else
3132     stream << "Connectivity not defined !\n";
3133 }
3134
3135 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3136 {
3137   const int *ptI=_nodal_connec_index->getConstPointer();
3138   const int *pt=_nodal_connec->getConstPointer();
3139   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3140     return ptI[cellId+1]-ptI[cellId]-1;
3141   else
3142     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3143 }
3144
3145 /*!
3146  * Returns types of cells of the specified part of \a this mesh.
3147  * This method avoids computing sub-mesh explicitely to get its types.
3148  *  \param [in] begin - an array of cell ids of interest.
3149  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3150  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3151  *         describing the cell types. 
3152  *  \throw If the coordinates array is not set.
3153  *  \throw If the nodal connectivity of cells is not defined.
3154  *  \sa getAllGeoTypes()
3155  */
3156 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3157 {
3158   checkFullyDefined();
3159   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3160   const int *conn=_nodal_connec->getConstPointer();
3161   const int *connIndex=_nodal_connec_index->getConstPointer();
3162   for(const int *w=begin;w!=end;w++)
3163     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3164   return ret;
3165 }
3166
3167 /*!
3168  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3169  * Optionally updates
3170  * a set of types of cells constituting \a this mesh. 
3171  * This method is for advanced users having prepared their connectivity before. For
3172  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3173  *  \param [in] conn - the nodal connectivity array. 
3174  *  \param [in] connIndex - the nodal connectivity index array.
3175  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3176  *         mesh is updated.
3177  */
3178 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3179 {
3180   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3181   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3182   if(isComputingTypes)
3183     computeTypes();
3184   declareAsNew();
3185 }
3186
3187 /*!
3188  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3189  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3190  */
3191 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3192     _nodal_connec(0),_nodal_connec_index(0),
3193     _types(other._types)
3194 {
3195   if(other._nodal_connec)
3196     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3197   if(other._nodal_connec_index)
3198     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3199 }
3200
3201 MEDCouplingUMesh::~MEDCouplingUMesh()
3202 {
3203   if(_nodal_connec)
3204     _nodal_connec->decrRef();
3205   if(_nodal_connec_index)
3206     _nodal_connec_index->decrRef();
3207 }
3208
3209 /*!
3210  * Recomputes a set of cell types of \a this mesh. For more info see
3211  * \ref MEDCouplingUMeshNodalConnectivity.
3212  */
3213 void MEDCouplingUMesh::computeTypes()
3214 {
3215   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3216 }
3217
3218 /*!
3219  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3220  */
3221 void MEDCouplingUMesh::checkFullyDefined() const
3222 {
3223   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3224     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3225 }
3226
3227 /*!
3228  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3229  */
3230 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3231 {
3232   if(!_nodal_connec_index || !_nodal_connec)
3233     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3234 }
3235
3236 /*!
3237  * Returns a number of cells constituting \a this mesh. 
3238  *  \return int - the number of cells in \a this mesh.
3239  *  \throw If the nodal connectivity of cells is not defined.
3240  */
3241 int MEDCouplingUMesh::getNumberOfCells() const
3242
3243   if(_nodal_connec_index)
3244     return _nodal_connec_index->getNumberOfTuples()-1;
3245   else
3246     if(_mesh_dim==-1)
3247       return 1;
3248     else
3249       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3250 }
3251
3252 /*!
3253  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3254  * mesh. For more info see \ref meshes.
3255  *  \return int - the dimension of \a this mesh.
3256  *  \throw If the mesh dimension is not defined using setMeshDimension().
3257  */
3258 int MEDCouplingUMesh::getMeshDimension() const
3259 {
3260   if(_mesh_dim<-1)
3261     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3262   return _mesh_dim;
3263 }
3264
3265 /*!
3266  * Returns a length of the nodal connectivity array.
3267  * This method is for test reason. Normally the integer returned is not useable by
3268  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3269  *  \return int - the length of the nodal connectivity array.
3270  */
3271 int MEDCouplingUMesh::getMeshLength() const
3272 {
3273   return _nodal_connec->getNbOfElems();
3274 }
3275
3276 /*!
3277  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3278  */
3279 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3280 {
3281   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3282   tinyInfo.push_back(getMeshDimension());
3283   tinyInfo.push_back(getNumberOfCells());
3284   if(_nodal_connec)
3285     tinyInfo.push_back(getMeshLength());
3286   else
3287     tinyInfo.push_back(-1);
3288 }
3289
3290 /*!
3291  * First step of unserialization process.
3292  */
3293 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3294 {
3295   return tinyInfo[6]<=0;
3296 }
3297
3298 /*!
3299  * Second step of serialization process.
3300  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3301  * \param a1
3302  * \param a2
3303  * \param littleStrings
3304  */
3305 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3306 {
3307   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3308   if(tinyInfo[5]!=-1)
3309     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3310 }
3311
3312 /*!
3313  * Third and final step of serialization process.
3314  */
3315 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3316 {
3317   MEDCouplingPointSet::serialize(a1,a2);
3318   if(getMeshDimension()>-1)
3319     {
3320       a1=DataArrayInt::New();
3321       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3322       int *ptA1=a1->getPointer();
3323       const int *conn=getNodalConnectivity()->getConstPointer();
3324       const int *index=getNodalConnectivityIndex()->getConstPointer();
3325       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3326       std::copy(conn,conn+getMeshLength(),ptA1);
3327     }
3328   else
3329     a1=0;
3330 }
3331
3332 /*!
3333  * Second and final unserialization process.
3334  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3335  */
3336 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3337 {
3338   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3339   setMeshDimension(tinyInfo[5]);
3340   if(tinyInfo[7]!=-1)
3341     {
3342       // Connectivity
3343       const int *recvBuffer=a1->getConstPointer();
3344       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3345       myConnecIndex->alloc(tinyInfo[6]+1,1);
3346       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3347       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3348       myConnec->alloc(tinyInfo[7],1);
3349       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3350       setConnectivity(myConnec, myConnecIndex);
3351     }
3352 }
3353
3354 /*!
3355  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3356  * CellIds are given using range specified by a start an end and step.
3357  */
3358 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3359 {
3360   checkFullyDefined();
3361   int ncell=getNumberOfCells();
3362   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3363   ret->_mesh_dim=_mesh_dim;
3364   ret->setCoords(_coords);
3365   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3366   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3367   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3368   int work=start;
3369   const int *conn=_nodal_connec->getConstPointer();
3370   const int *connIndex=_nodal_connec_index->getConstPointer();
3371   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3372     {
3373       if(work>=0 && work<ncell)
3374         {
3375           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3376         }
3377       else
3378         {
3379           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3380           throw INTERP_KERNEL::Exception(oss.str().c_str());
3381         }
3382     }
3383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3384   int *newConnPtr=newConn->getPointer();
3385   std::set<INTERP_KERNEL::NormalizedCellType> types;
3386   work=start;
3387   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3388     {
3389       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3390       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3391     }
3392   ret->setConnectivity(newConn,newConnI,false);
3393   ret->_types=types;
3394   ret->copyTinyInfoFrom(this);
3395   return ret.retn();
3396 }
3397
3398 /*!
3399  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3400  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3401  * The return newly allocated mesh will share the same coordinates as \a this.
3402  */
3403 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3404 {
3405   checkConnectivityFullyDefined();
3406   int ncell=getNumberOfCells();
3407   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3408   ret->_mesh_dim=_mesh_dim;
3409   ret->setCoords(_coords);
3410   std::size_t nbOfElemsRet=std::distance(begin,end);
3411   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3412   connIndexRet[0]=0;
3413   const int *conn=_nodal_connec->getConstPointer();
3414   const int *connIndex=_nodal_connec_index->getConstPointer();
3415   int newNbring=0;
3416   for(const int *work=begin;work!=end;work++,newNbring++)
3417     {
3418       if(*work>=0 && *work<ncell)
3419         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3420       else
3421         {
3422           free(connIndexRet);
3423           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3424           throw INTERP_KERNEL::Exception(oss.str().c_str());
3425         }
3426     }
3427   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3428   int *connRetWork=connRet;
3429   std::set<INTERP_KERNEL::NormalizedCellType> types;
3430   for(const int *work=begin;work!=end;work++)
3431     {
3432       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3433       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3434     }
3435   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3436   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3437   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3438   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3439   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3440   ret->_types=types;
3441   ret->copyTinyInfoFrom(this);
3442   return ret.retn();
3443 }
3444
3445 /*!
3446  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3447  * mesh.<br>
3448  * For 1D cells, the returned field contains lengths.<br>
3449  * For 2D cells, the returned field contains areas.<br>
3450  * For 3D cells, the returned field contains volumes.
3451  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3452  *         orientation, i.e. the volume is always positive.
3453  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3454  *         and one time . The caller is to delete this field using decrRef() as it is no
3455  *         more needed.
3456  */
3457 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3458 {
3459   std::string name="MeasureOfMesh_";
3460   name+=getName();
3461   int nbelem=getNumberOfCells();
3462   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3463   field->setName(name);
3464   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3465   array->alloc(nbelem,1);
3466   double *area_vol=array->getPointer();
3467   field->setArray(array) ; array=0;
3468   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3469   field->synchronizeTimeWithMesh();
3470   if(getMeshDimension()!=-1)
3471     {
3472       int ipt;
3473       INTERP_KERNEL::NormalizedCellType type;
3474       int dim_space=getSpaceDimension();
3475       const double *coords=getCoords()->getConstPointer();
3476       const int *connec=getNodalConnectivity()->getConstPointer();
3477       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3478       for(int iel=0;iel<nbelem;iel++)
3479         {
3480           ipt=connec_index[iel];
3481           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3482           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);
3483         }
3484       if(isAbs)
3485         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3486     }
3487   else
3488     {
3489       area_vol[0]=std::numeric_limits<double>::max();
3490     }
3491   return field.retn();
3492 }
3493
3494 /*!
3495  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3496  * mesh.<br>
3497  * For 1D cells, the returned array contains lengths.<br>
3498  * For 2D cells, the returned array contains areas.<br>
3499  * For 3D cells, the returned array contains volumes.
3500  * This method avoids building explicitly a part of \a this mesh to perform the work.
3501  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3502  *         orientation, i.e. the volume is always positive.
3503  *  \param [in] begin - an array of cell ids of interest.
3504  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3505  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3506  *          delete this array using decrRef() as it is no more needed.
3507  * 
3508  *  \if ENABLE_EXAMPLES
3509  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3510  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3511  *  \endif
3512  *  \sa getMeasureField()
3513  */
3514 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3515 {
3516   std::string name="PartMeasureOfMesh_";
3517   name+=getName();
3518   int nbelem=(int)std::distance(begin,end);
3519   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3520   array->setName(name);
3521   array->alloc(nbelem,1);
3522   double *area_vol=array->getPointer();
3523   if(getMeshDimension()!=-1)
3524     {
3525       int ipt;
3526       INTERP_KERNEL::NormalizedCellType type;
3527       int dim_space=getSpaceDimension();
3528       const double *coords=getCoords()->getConstPointer();
3529       const int *connec=getNodalConnectivity()->getConstPointer();
3530       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3531       for(const int *iel=begin;iel!=end;iel++)
3532         {
3533           ipt=connec_index[*iel];
3534           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3535           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3536         }
3537       if(isAbs)
3538         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3539     }
3540   else
3541     {
3542       area_vol[0]=std::numeric_limits<double>::max();
3543     }
3544   return array.retn();
3545 }
3546
3547 /*!
3548  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3549  * \a this one. The returned field contains the dual cell volume for each corresponding
3550  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3551  *  the dual mesh in P1 sens of \a this.<br>
3552  * For 1D cells, the returned field contains lengths.<br>
3553  * For 2D cells, the returned field contains areas.<br>
3554  * For 3D cells, the returned field contains volumes.
3555  * This method is useful to check "P1*" conservative interpolators.
3556  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3557  *         orientation, i.e. the volume is always positive.
3558  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3559  *          nodes and one time. The caller is to delete this array using decrRef() as
3560  *          it is no more needed.
3561  */
3562 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3563 {
3564   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3565   std::string name="MeasureOnNodeOfMesh_";
3566   name+=getName();
3567   int nbNodes=getNumberOfNodes();
3568   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3569   double cst=1./((double)getMeshDimension()+1.);
3570   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3571   array->alloc(nbNodes,1);
3572   double *valsToFill=array->getPointer();
3573   std::fill(valsToFill,valsToFill+nbNodes,0.);
3574   const double *values=tmp->getArray()->getConstPointer();
3575   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3576   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3577   getReverseNodalConnectivity(da,daInd);
3578   const int *daPtr=da->getConstPointer();
3579   const int *daIPtr=daInd->getConstPointer();
3580   for(int i=0;i<nbNodes;i++)
3581     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3582       valsToFill[i]+=cst*values[*cell];
3583   ret->setMesh(this);
3584   ret->setArray(array);
3585   return ret.retn();
3586 }
3587
3588 /*!
3589  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3590  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3591  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3592  * and are normalized.
3593  * <br> \a this can be either 
3594  * - a  2D mesh in 2D or 3D space or 
3595  * - an 1D mesh in 2D space.
3596  * 
3597  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3598  *          cells and one time. The caller is to delete this field using decrRef() as
3599  *          it is no more needed.
3600  *  \throw If the nodal connectivity of cells is not defined.
3601  *  \throw If the coordinates array is not set.
3602  *  \throw If the mesh dimension is not set.
3603  *  \throw If the mesh and space dimension is not as specified above.
3604  */
3605 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3606 {
3607   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3608     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3609   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3610   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3611   int nbOfCells=getNumberOfCells();
3612   int nbComp=getMeshDimension()+1;
3613   array->alloc(nbOfCells,nbComp);
3614   double *vals=array->getPointer();
3615   const int *connI=_nodal_connec_index->getConstPointer();
3616   const int *conn=_nodal_connec->getConstPointer();
3617   const double *coords=_coords->getConstPointer();
3618   if(getMeshDimension()==2)
3619     {
3620       if(getSpaceDimension()==3)
3621         {
3622           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3623           const double *locPtr=loc->getConstPointer();
3624           for(int i=0;i<nbOfCells;i++,vals+=3)
3625             {
3626               int offset=connI[i];
3627               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3628               double n=INTERP_KERNEL::norm<3>(vals);
3629               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3630             }
3631         }
3632       else
3633         {
3634           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3635           const double *isAbsPtr=isAbs->getArray()->begin();
3636           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3637             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3638         }
3639     }
3640   else//meshdimension==1
3641     {
3642       double tmp[2];
3643       for(int i=0;i<nbOfCells;i++)
3644         {
3645           int offset=connI[i];
3646           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3647           double n=INTERP_KERNEL::norm<2>(tmp);
3648           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3649           *vals++=-tmp[1];
3650           *vals++=tmp[0];
3651         }
3652     }
3653   ret->setArray(array);
3654   ret->setMesh(this);
3655   ret->synchronizeTimeWithSupport();
3656   return ret.retn();
3657 }
3658
3659 /*!
3660  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3661  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3662  * and are normalized.
3663  * <br> \a this can be either 
3664  * - a  2D mesh in 2D or 3D space or 
3665  * - an 1D mesh in 2D space.
3666  * 
3667  * This method avoids building explicitly a part of \a this mesh to perform the work.
3668  *  \param [in] begin - an array of cell ids of interest.
3669  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3670  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3671  *          cells and one time. The caller is to delete this field using decrRef() as
3672  *          it is no more needed.
3673  *  \throw If the nodal connectivity of cells is not defined.
3674  *  \throw If the coordinates array is not set.
3675  *  \throw If the mesh dimension is not set.
3676  *  \throw If the mesh and space dimension is not as specified above.
3677  *  \sa buildOrthogonalField()
3678  *
3679  *  \if ENABLE_EXAMPLES
3680  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3681  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3682  *  \endif
3683  */
3684 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3685 {
3686   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3687     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3688   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3689   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3690   std::size_t nbelems=std::distance(begin,end);
3691   int nbComp=getMeshDimension()+1;
3692   array->alloc((int)nbelems,nbComp);
3693   double *vals=array->getPointer();
3694   const int *connI=_nodal_connec_index->getConstPointer();
3695   const int *conn=_nodal_connec->getConstPointer();
3696   const double *coords=_coords->getConstPointer();
3697   if(getMeshDimension()==2)
3698     {
3699       if(getSpaceDimension()==3)
3700         {
3701           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3702           const double *locPtr=loc->getConstPointer();
3703           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3704             {
3705               int offset=connI[*i];
3706               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3707               double n=INTERP_KERNEL::norm<3>(vals);
3708               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3709             }
3710         }
3711       else
3712         {
3713           for(std::size_t i=0;i<nbelems;i++)
3714             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3715         }
3716     }
3717   else//meshdimension==1
3718     {
3719       double tmp[2];
3720       for(const int *i=begin;i!=end;i++)
3721         {
3722           int offset=connI[*i];
3723           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3724           double n=INTERP_KERNEL::norm<2>(tmp);
3725           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3726           *vals++=-tmp[1];
3727           *vals++=tmp[0];
3728         }
3729     }
3730   ret->setArray(array);
3731   ret->setMesh(this);
3732   ret->synchronizeTimeWithSupport();
3733   return ret.retn();
3734 }
3735
3736 /*!
3737  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3738  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3739  * and are \b not normalized.
3740  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3741  *          cells and one time. The caller is to delete this field using decrRef() as
3742  *          it is no more needed.
3743  *  \throw If the nodal connectivity of cells is not defined.
3744  *  \throw If the coordinates array is not set.
3745  *  \throw If \a this->getMeshDimension() != 1.
3746  *  \throw If \a this mesh includes cells of type other than SEG2.
3747  */
3748 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3749 {
3750   if(getMeshDimension()!=1)
3751     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3752   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3753     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3754   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3755   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3756   int nbOfCells=getNumberOfCells();
3757   int spaceDim=getSpaceDimension();
3758   array->alloc(nbOfCells,spaceDim);
3759   double *pt=array->getPointer();
3760   const double *coo=getCoords()->getConstPointer();
3761   std::vector<int> conn;
3762   conn.reserve(2);
3763   for(int i=0;i<nbOfCells;i++)
3764     {
3765       conn.resize(0);
3766       getNodeIdsOfCell(i,conn);
3767       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3768     }
3769   ret->setArray(array);
3770   ret->setMesh(this);
3771   ret->synchronizeTimeWithSupport();
3772   return ret.retn();
3773 }
3774
3775 /*!
3776  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3777  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3778  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3779  * from. If a result face is shared by two 3D cells, then the face in included twice in
3780  * the result mesh.
3781  *  \param [in] origin - 3 components of a point defining location of the plane.
3782  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3783  *         must be greater than 1e-6.
3784  *  \param [in] eps - half-thickness of the plane.
3785  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3786  *         producing correspondent 2D cells. The caller is to delete this array
3787  *         using decrRef() as it is no more needed.
3788  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3789  *         not share the node coordinates array with \a this mesh. The caller is to
3790  *         delete this mesh using decrRef() as it is no more needed.  
3791  *  \throw If the coordinates array is not set.
3792  *  \throw If the nodal connectivity of cells is not defined.
3793  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3794  *  \throw If magnitude of \a vec is less than 1e-6.
3795  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3796  *  \throw If \a this includes quadratic cells.
3797  */
3798 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3799 {
3800   checkFullyDefined();
3801   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3802     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3803   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3804   if(candidates->empty())
3805     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3806   std::vector<int> nodes;
3807   DataArrayInt *cellIds1D=0;
3808   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3809   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3811   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3812   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3814   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3815   revDesc2=0; revDescIndx2=0;
3816   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3817   revDesc1=0; revDescIndx1=0;
3818   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3819   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3820   //
3821   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3822   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3823     cut3DCurve[*it]=-1;
3824   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3825   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3826   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3827                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3828                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3829   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3830   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3831   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3832   if(cellIds2->empty())
3833     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3834   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3835   ret->setCoords(mDesc1->getCoords());
3836   ret->setConnectivity(conn,connI,true);
3837   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3838   return ret.retn();
3839 }
3840
3841 /*!
3842  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3843 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
3844 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3845 the result mesh.
3846  *  \param [in] origin - 3 components of a point defining location of the plane.
3847  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3848  *         must be greater than 1e-6.
3849  *  \param [in] eps - half-thickness of the plane.
3850  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3851  *         producing correspondent segments. The caller is to delete this array
3852  *         using decrRef() as it is no more needed.
3853  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3854  *         mesh in 3D space. This mesh does not share the node coordinates array with
3855  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3856  *         no more needed. 
3857  *  \throw If the coordinates array is not set.
3858  *  \throw If the nodal connectivity of cells is not defined.
3859  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3860  *  \throw If magnitude of \a vec is less than 1e-6.
3861  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3862  *  \throw If \a this includes quadratic cells.
3863  */
3864 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3865 {
3866   checkFullyDefined();
3867   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3868     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3869   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3870   if(candidates->empty())
3871     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3872   std::vector<int> nodes;
3873   DataArrayInt *cellIds1D=0;
3874   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3875   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3879   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3880   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3881   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3883   //
3884   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3885   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3886     cut3DCurve[*it]=-1;
3887   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3888   int ncellsSub=subMesh->getNumberOfCells();
3889   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3890   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3891                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3892                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3893   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3894   conn->alloc(0,1);
3895   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3896   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3897   for(int i=0;i<ncellsSub;i++)
3898     {
3899       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3900         {
3901           if(cut3DSurf[i].first!=-2)
3902             {
3903               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3904               connI->pushBackSilent(conn->getNumberOfTuples());
3905               cellIds2->pushBackSilent(i);
3906             }
3907           else
3908             {
3909               int cellId3DSurf=cut3DSurf[i].second;
3910               int offset=nodalI[cellId3DSurf]+1;
3911               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3912               for(int j=0;j<nbOfEdges;j++)
3913                 {
3914                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3915                   connI->pushBackSilent(conn->getNumberOfTuples());
3916                   cellIds2->pushBackSilent(cellId3DSurf);
3917                 }
3918             }
3919         }
3920     }
3921   if(cellIds2->empty())
3922     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3923   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3924   ret->setCoords(mDesc1->getCoords());
3925   ret->setConnectivity(conn,connI,true);
3926   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3927   return ret.retn();
3928 }
3929
3930 /*!
3931  * Finds cells whose bounding boxes intersect a given plane.
3932  *  \param [in] origin - 3 components of a point defining location of the plane.
3933  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3934  *         must be greater than 1e-6.
3935  *  \param [in] eps - half-thickness of the plane.
3936  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3937  *         cells. The caller is to delete this array using decrRef() as it is no more
3938  *         needed.
3939  *  \throw If the coordinates array is not set.
3940  *  \throw If the nodal connectivity of cells is not defined.
3941  *  \throw If \a this->getSpaceDimension() != 3.
3942  *  \throw If magnitude of \a vec is less than 1e-6.
3943  *  \sa buildSlice3D()
3944  */
3945 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3946 {
3947   checkFullyDefined();
3948   if(getSpaceDimension()!=3)
3949     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3950   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3951   if(normm<1e-6)
3952     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3953   double vec2[3];
3954   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3955   double angle=acos(vec[2]/normm);
3956   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3957   double bbox[6];
3958   if(angle>eps)
3959     {
3960       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3961       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3962       if(normm2/normm>1e-6)
3963         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3964       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3965       mw->setCoords(coo);
3966       mw->getBoundingBox(bbox);
3967       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3968       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3969     }
3970   else
3971     {
3972       getBoundingBox(bbox);
3973       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3974       cellIds=getCellsInBoundingBox(bbox,eps);
3975     }
3976   return cellIds.retn();
3977 }
3978
3979 /*!
3980  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3981  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3982  * No consideration of coordinate is done by this method.
3983  * 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)
3984  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3985  */
3986 bool MEDCouplingUMesh::isContiguous1D() const
3987 {
3988   if(getMeshDimension()!=1)
3989     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3990   int nbCells=getNumberOfCells();
3991   if(nbCells<1)
3992     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3993   const int *connI=_nodal_connec_index->getConstPointer();
3994   const int *conn=_nodal_connec->getConstPointer();
3995   int ref=conn[connI[0]+2];
3996   for(int i=1;i<nbCells;i++)
3997     {
3998       if(conn[connI[i]+1]!=ref)
3999         return false;
4000       ref=conn[connI[i]+2];
4001     }
4002   return true;
4003 }
4004
4005 /*!
4006  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4007  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4008  * \param pt reference point of the line
4009  * \param v normalized director vector of the line
4010  * \param eps max precision before throwing an exception
4011  * \param res output of size this->getNumberOfCells
4012  */
4013 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4014 {
4015   if(getMeshDimension()!=1)
4016     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4017   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4018     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4019   if(getSpaceDimension()!=3)
4020     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4021   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4022   const double *fPtr=f->getArray()->getConstPointer();
4023   double tmp[3];
4024   for(int i=0;i<getNumberOfCells();i++)
4025     {
4026       const double *tmp1=fPtr+3*i;
4027       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4028       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4029       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4030       double n1=INTERP_KERNEL::norm<3>(tmp);
4031       n1/=INTERP_KERNEL::norm<3>(tmp1);
4032       if(n1>eps)
4033         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4034     }
4035   const double *coo=getCoords()->getConstPointer();
4036   for(int i=0;i<getNumberOfNodes();i++)
4037     {
4038       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4039       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4040       res[i]=std::accumulate(tmp,tmp+3,0.);
4041     }
4042 }
4043
4044 /*!
4045  * 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. 
4046  * \a this is expected to be a mesh so that its space dimension is equal to its
4047  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4048  * 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).
4049  *
4050  * 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
4051  * 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).
4052  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4053  *
4054  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4055  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4056  *
4057  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4058  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4059  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4060  * \return the positive value of the distance.
4061  * \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
4062  * dimension - 1.
4063  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4064  */
4065 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4066 {
4067   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4068   if(meshDim!=spaceDim-1)
4069     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4070   if(meshDim!=2 && meshDim!=1)
4071     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4072   checkFullyDefined();
4073   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4074     { 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()); }
4075   DataArrayInt *ret1=0;
4076   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4077   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4078   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4079   cellId=*ret1Safe->begin();
4080   return *ret0->begin();
4081 }
4082
4083 /*!
4084  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4085  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4086  * 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
4087  * 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).
4088  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4089  * 
4090  * \a this is expected to be a mesh so that its space dimension is equal to its
4091  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4092  * 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).
4093  *
4094  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4095  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4096  *
4097  * \param [in] pts the list of points in which each tuple represents a point
4098  * \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.
4099  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4100  * \throw if number of components of \a pts is not equal to the space dimension.
4101  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4102  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4103  */
4104 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4105 {
4106   if(!pts)
4107     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4108   pts->checkAllocated();
4109   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4110   if(meshDim!=spaceDim-1)
4111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4112   if(meshDim!=2 && meshDim!=1)
4113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4114   if(pts->getNumberOfComponents()!=spaceDim)
4115     {
4116       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4117       throw INTERP_KERNEL::Exception(oss.str().c_str());
4118     }
4119   checkFullyDefined();
4120   int nbCells=getNumberOfCells();
4121   if(nbCells==0)
4122     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4123   int nbOfPts=pts->getNumberOfTuples();
4124   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4125   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4126   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4127   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4128   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4129   const double *bbox(bboxArr->begin());
4130   switch(spaceDim)
4131   {
4132     case 3:
4133       {
4134         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4135         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4136           {
4137             double x=std::numeric_limits<double>::max();
4138             std::vector<int> elems;
4139             myTree.getMinDistanceOfMax(ptsPtr,x);
4140             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4141             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4142           }
4143         break;
4144       }
4145     case 2:
4146       {
4147         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4148         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4149           {
4150             double x=std::numeric_limits<double>::max();
4151             std::vector<int> elems;
4152             myTree.getMinDistanceOfMax(ptsPtr,x);
4153             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4154             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4155           }
4156         break;
4157       }
4158     default:
4159       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4160   }
4161   cellIds=ret1.retn();
4162   return ret0.retn();
4163 }
4164
4165 /// @cond INTERNAL
4166
4167 /*!
4168  * \param [in] pt the start pointer (included) of the coordinates of the point
4169  * \param [in] cellIdsBg the start pointer (included) of cellIds
4170  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4171  * \param [in] nc nodal connectivity
4172  * \param [in] ncI nodal connectivity index
4173  * \param [in,out] ret0 the min distance between \a this and the external input point
4174  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4175  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4176  */
4177 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)
4178 {
4179   cellId=-1;
4180   ret0=std::numeric_limits<double>::max();
4181   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4182     {
4183       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4184       {
4185         case INTERP_KERNEL::NORM_TRI3:
4186           {
4187             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4188             if(tmp<ret0)
4189               { ret0=tmp; cellId=*zeCell; }
4190             break;
4191           }
4192         case INTERP_KERNEL::NORM_QUAD4:
4193         case INTERP_KERNEL::NORM_POLYGON:
4194           {
4195             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4196             if(tmp<ret0)
4197               { ret0=tmp; cellId=*zeCell; }
4198             break;
4199           }
4200         default:
4201           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4202       }
4203     }
4204 }
4205
4206 /*!
4207  * \param [in] pt the start pointer (included) of the coordinates of the point
4208  * \param [in] cellIdsBg the start pointer (included) of cellIds
4209  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4210  * \param [in] nc nodal connectivity
4211  * \param [in] ncI nodal connectivity index
4212  * \param [in,out] ret0 the min distance between \a this and the external input point
4213  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4214  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4215  */
4216 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)
4217 {
4218   cellId=-1;
4219   ret0=std::numeric_limits<double>::max();
4220   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4221     {
4222       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4223       {
4224         case INTERP_KERNEL::NORM_SEG2:
4225           {
4226             std::size_t uselessEntry=0;
4227             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4228             tmp=sqrt(tmp);
4229             if(tmp<ret0)
4230               { ret0=tmp; cellId=*zeCell; }
4231             break;
4232           }
4233         default:
4234           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4235       }
4236     }
4237 }
4238 /// @endcond
4239
4240 /*!
4241  * Finds cells in contact with a ball (i.e. a point with precision). 
4242  * 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.
4243  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4244  *
4245  * \warning This method is suitable if the caller intends to evaluate only one
4246  *          point, for more points getCellsContainingPoints() is recommended as it is
4247  *          faster. 
4248  *  \param [in] pos - array of coordinates of the ball central point.
4249  *  \param [in] eps - ball radius.
4250  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4251  *         if there are no such cells.
4252  *  \throw If the coordinates array is not set.
4253  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4254  */
4255 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4256 {
4257   std::vector<int> elts;
4258   getCellsContainingPoint(pos,eps,elts);
4259   if(elts.empty())
4260     return -1;
4261   return elts.front();
4262 }
4263
4264 /*!
4265  * Finds cells in contact with a ball (i.e. a point with precision).
4266  * 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.
4267  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4268  * \warning This method is suitable if the caller intends to evaluate only one
4269  *          point, for more points getCellsContainingPoints() is recommended as it is
4270  *          faster. 
4271  *  \param [in] pos - array of coordinates of the ball central point.
4272  *  \param [in] eps - ball radius.
4273  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4274  *         before inserting ids.
4275  *  \throw If the coordinates array is not set.
4276  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4277  *
4278  *  \if ENABLE_EXAMPLES
4279  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4280  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4281  *  \endif
4282  */
4283 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4284 {
4285   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4286   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4287   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4288 }
4289
4290 /// @cond INTERNAL
4291
4292 namespace ParaMEDMEM
4293 {
4294   template<const int SPACEDIMM>
4295   class DummyClsMCUG
4296   {
4297   public:
4298     static const int MY_SPACEDIM=SPACEDIMM;
4299     static const int MY_MESHDIM=8;
4300     typedef int MyConnType;
4301     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4302     // begin
4303     // useless, but for windows compilation ...
4304     const double* getCoordinatesPtr() const { return 0; }
4305     const int* getConnectivityPtr() const { return 0; }
4306     const int* getConnectivityIndexPtr() const { return 0; }
4307     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4308     // end
4309   };
4310
4311   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4312   {
4313     INTERP_KERNEL::Edge *ret(0);
4314     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]));
4315     m[n0]=bg[0]; m[n1]=bg[1];
4316     switch(typ)
4317     {
4318       case INTERP_KERNEL::NORM_SEG2:
4319         {
4320           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4321           break;
4322         }
4323       case INTERP_KERNEL::NORM_SEG3:
4324         {
4325           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4326           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4327           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4328           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4329           bool colinearity(inters.areColinears());
4330           delete e1; delete e2;
4331           if(colinearity)
4332             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4333           else
4334             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4335           break;
4336         }
4337       default:
4338         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4339     }
4340     return ret;
4341   }
4342
4343   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4344   {
4345     INTERP_KERNEL::Edge *ret=0;
4346     switch(typ)
4347     {
4348       case INTERP_KERNEL::NORM_SEG2:
4349         {
4350           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4351           break;
4352         }
4353       case INTERP_KERNEL::NORM_SEG3:
4354         {
4355           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4356           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4357           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4358           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4359           bool colinearity=inters.areColinears();
4360           delete e1; delete e2;
4361           if(colinearity)
4362             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4363           else
4364             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4365           mapp2[bg[2]].second=false;
4366           break;
4367         }
4368       default:
4369         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4370     }
4371     return ret;
4372   }
4373
4374   /*!
4375    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4376    * the global mesh 'mDesc'.
4377    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4378    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4379    */
4380   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4381                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4382   {
4383     mapp.clear();
4384     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.
4385     const double *coo=mDesc->getCoords()->getConstPointer();
4386     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4387     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4388     std::set<int> s;
4389     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4390       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4391     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4392       {
4393         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4394         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4395       }
4396     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4397     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4398       {
4399         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4400         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4401       }
4402     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4403       {
4404         if((*it2).second.second)
4405           mapp[(*it2).second.first]=(*it2).first;
4406         ((*it2).second.first)->decrRef();
4407       }
4408     return ret;
4409   }
4410
4411   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4412   {
4413     if(nodeId>=offset2)
4414       {
4415         int locId=nodeId-offset2;
4416         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4417       }
4418     if(nodeId>=offset1)
4419       {
4420         int locId=nodeId-offset1;
4421         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4422       }
4423     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4424   }
4425
4426   /**
4427    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4428    */
4429   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4430                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4431                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4432   {
4433     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4434       {
4435         int eltId1=abs(*desc1)-1;
4436         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4437           {
4438             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4439             if(it==mappRev.end())
4440               {
4441                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4442                 mapp[node]=*it1;
4443                 mappRev[*it1]=node;
4444               }
4445           }
4446       }
4447   }
4448 }
4449
4450 /// @endcond
4451
4452 template<int SPACEDIM>
4453 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4454                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4455 {
4456   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4457   int *eltsIndexPtr(eltsIndex->getPointer());
4458   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4459   const double *bbox(bboxArr->begin());
4460   int nbOfCells=getNumberOfCells();
4461   const int *conn=_nodal_connec->getConstPointer();
4462   const int *connI=_nodal_connec_index->getConstPointer();
4463   double bb[2*SPACEDIM];
4464   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4465   for(int i=0;i<nbOfPoints;i++)
4466     {
4467       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4468       for(int j=0;j<SPACEDIM;j++)
4469         {
4470           bb[2*j]=pos[SPACEDIM*i+j];
4471           bb[2*j+1]=pos[SPACEDIM*i+j];
4472         }
4473       std::vector<int> candidates;
4474       myTree.getIntersectingElems(bb,candidates);
4475       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4476         {
4477           int sz(connI[(*iter)+1]-connI[*iter]-1);
4478           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4479           bool status(false);
4480           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4481             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4482           else
4483             {
4484               if(SPACEDIM!=2)
4485                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4486               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4487               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4488               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4489               INTERP_KERNEL::QuadraticPolygon *pol(0);
4490               for(int j=0;j<sz;j++)
4491                 {
4492                   int nodeId(conn[connI[*iter]+1+j]);
4493                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4494                 }
4495               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4496                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4497               else
4498                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4499               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4500               double a(0.),b(0.),c(0.);
4501               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4502               status=pol->isInOrOut2(n);
4503               delete pol; n->decrRef();
4504             }
4505           if(status)
4506             {
4507               eltsIndexPtr[i+1]++;
4508               elts->pushBackSilent(*iter);
4509             }
4510         }
4511     }
4512 }
4513 /*!
4514  * Finds cells in contact with several balls (i.e. points with precision).
4515  * This method is an extension of getCellContainingPoint() and
4516  * getCellsContainingPoint() for the case of multiple points.
4517  * 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.
4518  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4519  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4520  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4521  *         this->getSpaceDimension() * \a nbOfPoints 
4522  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4523  *  \param [in] eps - radius of balls (i.e. the precision).
4524  *  \param [out] elts - vector returning ids of found cells.
4525  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4526  *         dividing cell ids in \a elts into groups each referring to one
4527  *         point. Its every element (except the last one) is an index pointing to the
4528  *         first id of a group of cells. For example cells in contact with the *i*-th
4529  *         point are described by following range of indices:
4530  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4531  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4532  *         Number of cells in contact with the *i*-th point is
4533  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4534  *  \throw If the coordinates array is not set.
4535  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4536  *
4537  *  \if ENABLE_EXAMPLES
4538  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4539  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4540  *  \endif
4541  */
4542 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4543                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4544 {
4545   int spaceDim=getSpaceDimension();
4546   int mDim=getMeshDimension();
4547   if(spaceDim==3)
4548     {
4549       if(mDim==3)
4550         {
4551           const double *coords=_coords->getConstPointer();
4552           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4553         }
4554       /*else if(mDim==2)
4555         {
4556
4557         }*/
4558       else
4559         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4560     }
4561   else if(spaceDim==2)
4562     {
4563       if(mDim==2)
4564         {
4565           const double *coords=_coords->getConstPointer();
4566           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4567         }
4568       else
4569         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4570     }
4571   else if(spaceDim==1)
4572     {
4573       if(mDim==1)
4574         {
4575           const double *coords=_coords->getConstPointer();
4576           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4577         }
4578       else
4579         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4580     }
4581   else
4582     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4583 }
4584
4585 /*!
4586  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4587  * least two its edges intersect each other anywhere except their extremities. An
4588  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4589  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4590  *         cleared before filling in.
4591  *  \param [in] eps - precision.
4592  *  \throw If \a this->getMeshDimension() != 2.
4593  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4594  */
4595 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4596 {
4597   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4598   if(getMeshDimension()!=2)
4599     throw INTERP_KERNEL::Exception(msg);
4600   int spaceDim=getSpaceDimension();
4601   if(spaceDim!=2 && spaceDim!=3)
4602     throw INTERP_KERNEL::Exception(msg);
4603   const int *conn=_nodal_connec->getConstPointer();
4604   const int *connI=_nodal_connec_index->getConstPointer();
4605   int nbOfCells=getNumberOfCells();
4606   std::vector<double> cell2DinS2;
4607   for(int i=0;i<nbOfCells;i++)
4608     {
4609       int offset=connI[i];
4610       int nbOfNodesForCell=connI[i+1]-offset-1;
4611       if(nbOfNodesForCell<=3)
4612         continue;
4613       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4614       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4615       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4616         cells.push_back(i);
4617       cell2DinS2.clear();
4618     }
4619 }
4620
4621 /*!
4622  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4623  *
4624  * 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.
4625  * 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.
4626  * 
4627  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4628  * This convex envelop is computed using Jarvis march algorithm.
4629  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4630  * 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)
4631  * 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.
4632  *
4633  * \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.
4634  * \sa MEDCouplingUMesh::colinearize2D
4635  */
4636 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4637 {
4638   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4639     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4640   checkFullyDefined();
4641   const double *coords=getCoords()->getConstPointer();
4642   int nbOfCells=getNumberOfCells();
4643   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4644   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4645   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4646   int *workIndexOut=nodalConnecIndexOut->getPointer();
4647   *workIndexOut=0;
4648   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4649   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4650   std::set<INTERP_KERNEL::NormalizedCellType> types;
4651   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4652   isChanged->alloc(0,1);
4653   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4654     {
4655       int pos=nodalConnecOut->getNumberOfTuples();
4656       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4657         isChanged->pushBackSilent(i);
4658       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4659       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4660     }
4661   if(isChanged->empty())
4662     return 0;
4663   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4664   _types=types;
4665   return isChanged.retn();
4666 }
4667
4668 /*!
4669  * This method is \b NOT const because it can modify \a this.
4670  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4671  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4672  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4673  * \b 1 for translation and rotation around point of 'mesh1D'.
4674  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4675  */
4676 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4677 {
4678   checkFullyDefined();
4679   mesh1D->checkFullyDefined();
4680   if(!mesh1D->isContiguous1D())
4681     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4682   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4683     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4684   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4685     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4686   if(mesh1D->getMeshDimension()!=1)
4687     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4688   bool isQuad=false;
4689   if(isPresenceOfQuadratic())
4690     {
4691       if(mesh1D->isFullyQuadratic())
4692         isQuad=true;
4693       else
4694         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4695     }
4696   int oldNbOfNodes(getNumberOfNodes());
4697   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4698   switch(policy)
4699   {
4700     case 0:
4701       {
4702         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4703         break;
4704       }
4705     case 1:
4706       {
4707         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4708         break;
4709       }
4710     default:
4711       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4712   }
4713   setCoords(newCoords);
4714   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4715   updateTime();
4716   return ret.retn();
4717 }
4718
4719 /*!
4720  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4721  * If it is not the case an exception will be thrown.
4722  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4723  * intersection of plane defined by ('origin','vec').
4724  * This method has one in/out parameter : 'cut3DCurve'.
4725  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4726  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4727  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4728  * This method will throw an exception if \a this contains a non linear segment.
4729  */
4730 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4731 {
4732   checkFullyDefined();
4733   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4734     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4735   int ncells=getNumberOfCells();
4736   int nnodes=getNumberOfNodes();
4737   double vec2[3],vec3[3],vec4[3];
4738   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4739   if(normm<1e-6)
4740     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4741   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4742   const int *conn=_nodal_connec->getConstPointer();
4743   const int *connI=_nodal_connec_index->getConstPointer();
4744   const double *coo=_coords->getConstPointer();
4745   std::vector<double> addCoo;
4746   for(int i=0;i<ncells;i++)
4747     {
4748       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4749         {
4750           if(cut3DCurve[i]==-2)
4751             {
4752               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4753               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];
4754               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4755               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4756               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4757                 {
4758                   const double *st2=coo+3*st;
4759                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4760                   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]));
4761                   if(pos>eps && pos<1-eps)
4762                     {
4763                       int nNode=((int)addCoo.size())/3;
4764                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4765                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4766                       cut3DCurve[i]=nnodes+nNode;
4767                     }
4768                 }
4769             }
4770         }
4771       else
4772         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4773     }
4774   if(!addCoo.empty())
4775     {
4776       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4777       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4778       coo2->alloc(newNbOfNodes,3);
4779       double *tmp=coo2->getPointer();
4780       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4781       std::copy(addCoo.begin(),addCoo.end(),tmp);
4782       DataArrayDouble::SetArrayIn(coo2,_coords);
4783     }
4784 }
4785
4786 /*!
4787  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4788  * \param mesh1D is the input 1D mesh used for translation computation.
4789  * \return newCoords new coords filled by this method. 
4790  */
4791 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4792 {
4793   int oldNbOfNodes=getNumberOfNodes();
4794   int nbOf1DCells=mesh1D->getNumberOfCells();
4795   int spaceDim=getSpaceDimension();
4796   DataArrayDouble *ret=DataArrayDouble::New();
4797   std::vector<bool> isQuads;
4798   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4799   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4800   double *retPtr=ret->getPointer();
4801   const double *coords=getCoords()->getConstPointer();
4802   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4803   std::vector<int> v;
4804   std::vector<double> c;
4805   double vec[3];
4806   v.reserve(3);
4807   c.reserve(6);
4808   for(int i=0;i<nbOf1DCells;i++)
4809     {
4810       v.resize(0);
4811       mesh1D->getNodeIdsOfCell(i,v);
4812       c.resize(0);
4813       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4814       mesh1D->getCoordinatesOfNode(v[0],c);
4815       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4816       for(int j=0;j<oldNbOfNodes;j++)
4817         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4818       if(isQuad)
4819         {
4820           c.resize(0);
4821           mesh1D->getCoordinatesOfNode(v[1],c);
4822           mesh1D->getCoordinatesOfNode(v[0],c);
4823           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4824           for(int j=0;j<oldNbOfNodes;j++)
4825             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4826         }
4827     }
4828   ret->copyStringInfoFrom(*getCoords());
4829   return ret;
4830 }
4831
4832 /*!
4833  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4834  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4835  * \return newCoords new coords filled by this method. 
4836  */
4837 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4838 {
4839   if(mesh1D->getSpaceDimension()==2)
4840     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4841   if(mesh1D->getSpaceDimension()==3)
4842     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4843   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4844 }
4845
4846 /*!
4847  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4848  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4849  * \return newCoords new coords filled by this method. 
4850  */
4851 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4852 {
4853   if(isQuad)
4854     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4855   int oldNbOfNodes=getNumberOfNodes();
4856   int nbOf1DCells=mesh1D->getNumberOfCells();
4857   if(nbOf1DCells<2)
4858     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4859   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4860   int nbOfLevsInVec=nbOf1DCells+1;
4861   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4862   double *retPtr=ret->getPointer();
4863   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4864   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4865   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4866   tmp->setCoords(tmp2);
4867   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4868   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4869   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4870   for(int i=1;i<nbOfLevsInVec;i++)
4871     {
4872       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4873       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4874       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4875       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4876       tmp->translate(vec);
4877       double tmp3[2],radius,alpha,alpha0;
4878       const double *p0=i+1<nbOfLevsInVec?begin:third;
4879       const double *p1=i+1<nbOfLevsInVec?end:begin;
4880       const double *p2=i+1<nbOfLevsInVec?third:end;
4881       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4882       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]);
4883       double angle=acos(cosangle/(radius*radius));
4884       tmp->rotate(end,0,angle);
4885       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4886     }
4887   return ret.retn();
4888 }
4889
4890 /*!
4891  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4892  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4893  * \return newCoords new coords filled by this method. 
4894  */
4895 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4896 {
4897   if(isQuad)
4898     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4899   int oldNbOfNodes=getNumberOfNodes();
4900   int nbOf1DCells=mesh1D->getNumberOfCells();
4901   if(nbOf1DCells<2)
4902     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4903   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4904   int nbOfLevsInVec=nbOf1DCells+1;
4905   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4906   double *retPtr=ret->getPointer();
4907   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4908   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4909   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4910   tmp->setCoords(tmp2);
4911   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4912   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4913   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4914   for(int i=1;i<nbOfLevsInVec;i++)
4915     {
4916       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4917       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4918       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4919       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4920       tmp->translate(vec);
4921       double tmp3[2],radius,alpha,alpha0;
4922       const double *p0=i+1<nbOfLevsInVec?begin:third;
4923       const double *p1=i+1<nbOfLevsInVec?end:begin;
4924       const double *p2=i+1<nbOfLevsInVec?third:end;
4925       double vecPlane[3]={
4926         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4927         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4928         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4929       };
4930       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4931       if(norm>1.e-7)
4932         {
4933           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4934           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4935           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4936           double s2=norm2;
4937           double c2=cos(asin(s2));
4938           double m[3][3]={
4939             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4940             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4941             {-vec2[1]*s2, vec2[0]*s2, c2}
4942           };
4943           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]};
4944           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]};
4945           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]};
4946           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4947           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]);
4948           double angle=acos(cosangle/(radius*radius));
4949           tmp->rotate(end,vecPlane,angle);
4950         }
4951       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4952     }
4953   return ret.retn();
4954 }
4955
4956 /*!
4957  * This method is private because not easy to use for end user. This method is const contrary to
4958  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4959  * the coords sorted slice by slice.
4960  * \param isQuad specifies presence of quadratic cells.
4961  */
4962 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4963 {
4964   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4965   int nbOf2DCells(getNumberOfCells());
4966   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4967   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4968   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4969   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4970   newConnI->alloc(nbOf3DCells+1,1);
4971   int *newConnIPtr(newConnI->getPointer());
4972   *newConnIPtr++=0;
4973   std::vector<int> newc;
4974   for(int j=0;j<nbOf2DCells;j++)
4975     {
4976       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4977       *newConnIPtr++=(int)newc.size();
4978     }
4979   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4980   int *newConnPtr(newConn->getPointer());
4981   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4982   newConnIPtr=newConnI->getPointer();
4983   for(int iz=0;iz<nbOf1DCells;iz++)
4984     {
4985       if(iz!=0)
4986         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4987       const int *posOfTypeOfCell(newConnIPtr);
4988       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4989         {
4990           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4991           if(icell!=*posOfTypeOfCell)
4992             {
4993               if(*iter!=-1)
4994                 *newConnPtr=(*iter)+iz*deltaPerLev;
4995               else
4996                 *newConnPtr=-1;
4997             }
4998           else
4999             {
5000               *newConnPtr=*iter;
5001               posOfTypeOfCell++;
5002             }
5003         }
5004     }
5005   ret->setConnectivity(newConn,newConnI,true);
5006   ret->setCoords(getCoords());
5007   return ret;
5008 }
5009
5010 /*!
5011  * Checks if \a this mesh is constituted by only quadratic cells.
5012  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
5013  *  \throw If the coordinates array is not set.
5014  *  \throw If the nodal connectivity of cells is not defined.
5015  */
5016 bool MEDCouplingUMesh::isFullyQuadratic() const
5017 {
5018   checkFullyDefined();
5019   bool ret=true;
5020   int nbOfCells=getNumberOfCells();
5021   for(int i=0;i<nbOfCells && ret;i++)
5022     {
5023       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5024       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5025       ret=cm.isQuadratic();
5026     }
5027   return ret;
5028 }
5029
5030 /*!
5031  * Checks if \a this mesh includes any quadratic cell.
5032  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5033  *  \throw If the coordinates array is not set.
5034  *  \throw If the nodal connectivity of cells is not defined.
5035  */
5036 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5037 {
5038   checkFullyDefined();
5039   bool ret=false;
5040   int nbOfCells=getNumberOfCells();
5041   for(int i=0;i<nbOfCells && !ret;i++)
5042     {
5043       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5044       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5045       ret=cm.isQuadratic();
5046     }
5047   return ret;
5048 }
5049
5050 /*!
5051  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5052  * this mesh, it remains unchanged.
5053  *  \throw If the coordinates array is not set.
5054  *  \throw If the nodal connectivity of cells is not defined.
5055  */
5056 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5057 {
5058   checkFullyDefined();
5059   int nbOfCells=getNumberOfCells();
5060   int delta=0;
5061   const int *iciptr=_nodal_connec_index->getConstPointer();
5062   for(int i=0;i<nbOfCells;i++)
5063     {
5064       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5065       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5066       if(cm.isQuadratic())
5067         {
5068           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5069           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5070           if(!cml.isDynamic())
5071             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5072           else
5073             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5074         }
5075     }
5076   if(delta==0)
5077     return ;
5078   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5079   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5080   const int *icptr=_nodal_connec->getConstPointer();
5081   newConn->alloc(getMeshLength()-delta,1);
5082   newConnI->alloc(nbOfCells+1,1);
5083   int *ocptr=newConn->getPointer();
5084   int *ociptr=newConnI->getPointer();
5085   *ociptr=0;
5086   _types.clear();
5087   for(int i=0;i<nbOfCells;i++,ociptr++)
5088     {
5089       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5090       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5091       if(!cm.isQuadratic())
5092         {
5093           _types.insert(type);
5094           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5095           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5096         }
5097       else
5098         {
5099           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5100           _types.insert(typel);
5101           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5102           int newNbOfNodes=cml.getNumberOfNodes();
5103           if(cml.isDynamic())
5104             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5105           *ocptr++=(int)typel;
5106           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5107           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5108         }
5109     }
5110   setConnectivity(newConn,newConnI,false);
5111 }
5112
5113 /*!
5114  * This method converts all linear cell in \a this to quadratic one.
5115  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5116  * 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)
5117  * 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.
5118  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5119  * end of the existing coordinates.
5120  * 
5121  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5122  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5123  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5124  * 
5125  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5126  *
5127  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5128  */
5129 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5130 {
5131   DataArrayInt *conn=0,*connI=0;
5132   DataArrayDouble *coords=0;
5133   std::set<INTERP_KERNEL::NormalizedCellType> types;
5134   checkFullyDefined();
5135   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5136   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5137   int meshDim=getMeshDimension();
5138   switch(conversionType)
5139   {
5140     case 0:
5141       switch(meshDim)
5142       {
5143         case 1:
5144           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5145           connSafe=conn; connISafe=connI; coordsSafe=coords;
5146           break;
5147         case 2:
5148           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5149           connSafe=conn; connISafe=connI; coordsSafe=coords;
5150           break;
5151         case 3:
5152           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5153           connSafe=conn; connISafe=connI; coordsSafe=coords;
5154           break;
5155         default:
5156           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5157       }
5158       break;
5159         case 1:
5160           {
5161             switch(meshDim)
5162             {
5163               case 1:
5164                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5165                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5166                 break;
5167               case 2:
5168                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5169                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5170                 break;
5171               case 3:
5172                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5173                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5174                 break;
5175               default:
5176                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5177             }
5178             break;
5179           }
5180         default:
5181           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5182   }
5183   setConnectivity(connSafe,connISafe,false);
5184   _types=types;
5185   setCoords(coordsSafe);
5186   return ret.retn();
5187 }
5188
5189 #if 0
5190 /*!
5191  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5192  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5193  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5194  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5195  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5196  * This method can be seen as the opposite method of colinearize2D.
5197  * 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
5198  * to avoid to modify the numbering of existing nodes.
5199  *
5200  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5201  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5202  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5203  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5204  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5205  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5206  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5207  *
5208  * \sa buildDescendingConnectivity2
5209  */
5210 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5211                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5212 {
5213   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5214     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5215   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5216   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5217     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5218   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5219     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5220   //DataArrayInt *out0(0),*outi0(0);
5221   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5222   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5223   //out0s=out0s->buildUnique(); out0s->sort(true);
5224 }
5225 #endif
5226
5227 /*!
5228  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5229  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5230  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5231  */
5232 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5233 {
5234   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5235   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5236   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5238   int nbOfCells=getNumberOfCells();
5239   int nbOfNodes=getNumberOfNodes();
5240   const int *cPtr=_nodal_connec->getConstPointer();
5241   const int *icPtr=_nodal_connec_index->getConstPointer();
5242   int lastVal=0,offset=nbOfNodes;
5243   for(int i=0;i<nbOfCells;i++,icPtr++)
5244     {
5245       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5246       if(type==INTERP_KERNEL::NORM_SEG2)
5247         {
5248           types.insert(INTERP_KERNEL::NORM_SEG3);
5249           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5250           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5251           newConn->pushBackSilent(offset++);
5252           lastVal+=4;
5253           newConnI->pushBackSilent(lastVal);
5254           ret->pushBackSilent(i);
5255         }
5256       else
5257         {
5258           types.insert(type);
5259           lastVal+=(icPtr[1]-icPtr[0]);
5260           newConnI->pushBackSilent(lastVal);
5261           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5262         }
5263     }
5264   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5265   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5266   return ret.retn();
5267 }
5268
5269 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
5270 {
5271   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5273   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5274   //
5275   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5276   DataArrayInt *conn1D=0,*conn1DI=0;
5277   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5278   DataArrayDouble *coordsTmp=0;
5279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5280   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5281   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5282   const int *c1DPtr=conn1D->begin();
5283   const int *c1DIPtr=conn1DI->begin();
5284   int nbOfCells=getNumberOfCells();
5285   const int *cPtr=_nodal_connec->getConstPointer();
5286   const int *icPtr=_nodal_connec_index->getConstPointer();
5287   int lastVal=0;
5288   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5289     {
5290       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5291       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5292       if(!cm.isQuadratic())
5293         {
5294           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5295           types.insert(typ2); newConn->pushBackSilent(typ2);
5296           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5297           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5298             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5299           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5300           newConnI->pushBackSilent(lastVal);
5301           ret->pushBackSilent(i);
5302         }
5303       else
5304         {
5305           types.insert(typ);
5306           lastVal+=(icPtr[1]-icPtr[0]);
5307           newConnI->pushBackSilent(lastVal);
5308           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5309         }
5310     }
5311   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5312   return ret.retn();
5313 }
5314
5315 /*!
5316  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5317  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5318  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5319  */
5320 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5321 {
5322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5323   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5324   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5325 }
5326
5327 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5328 {
5329   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5330   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5331   //
5332   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5333   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5334   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5335   //
5336   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5337   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5338   DataArrayInt *conn1D=0,*conn1DI=0;
5339   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5340   DataArrayDouble *coordsTmp=0;
5341   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5342   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5344   const int *c1DPtr=conn1D->begin();
5345   const int *c1DIPtr=conn1DI->begin();
5346   int nbOfCells=getNumberOfCells();
5347   const int *cPtr=_nodal_connec->getConstPointer();
5348   const int *icPtr=_nodal_connec_index->getConstPointer();
5349   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5350   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5351     {
5352       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5353       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5354       if(!cm.isQuadratic())
5355         {
5356           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5357           types.insert(typ2); newConn->pushBackSilent(typ2);
5358           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5359           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5360             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5361           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5362           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5363           newConnI->pushBackSilent(lastVal);
5364           ret->pushBackSilent(i);
5365         }
5366       else
5367         {
5368           types.insert(typ);
5369           lastVal+=(icPtr[1]-icPtr[0]);
5370           newConnI->pushBackSilent(lastVal);
5371           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5372         }
5373     }
5374   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5375   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5376   return ret.retn();
5377 }
5378
5379 /*!
5380  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5381  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5382  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5383  */
5384 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5385 {
5386   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5387   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5388   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5389 }
5390
5391 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5392 {
5393   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5394   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5395   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5396   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5397   //
5398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5400   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5401   //
5402   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5403   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5404   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5405   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5406   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5407   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5408   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5409   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5410   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5411   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5413   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5414   int nbOfCells=getNumberOfCells();
5415   const int *cPtr=_nodal_connec->getConstPointer();
5416   const int *icPtr=_nodal_connec_index->getConstPointer();
5417   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5418   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5419     {
5420       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5421       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5422       if(!cm.isQuadratic())
5423         {
5424           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5425           if(typ2==INTERP_KERNEL::NORM_ERROR)
5426             {
5427               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5428               throw INTERP_KERNEL::Exception(oss.str().c_str());
5429             }
5430           types.insert(typ2); newConn->pushBackSilent(typ2);
5431           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5432           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5433             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5434           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5435             {
5436               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5437               int tmpPos=newConn->getNumberOfTuples();
5438               newConn->pushBackSilent(nodeId2);
5439               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5440             }
5441           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5442           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5443           newConnI->pushBackSilent(lastVal);
5444           ret->pushBackSilent(i);
5445         }
5446       else
5447         {
5448           types.insert(typ);
5449           lastVal+=(icPtr[1]-icPtr[0]);
5450           newConnI->pushBackSilent(lastVal);
5451           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5452         }
5453     }
5454   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5455   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5456   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5457   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5458   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5459   int *c=newConn->getPointer();
5460   const int *cI(newConnI->begin());
5461   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5462     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5463   offset=coordsTmp2Safe->getNumberOfTuples();
5464   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5465     c[cI[(*elt)+1]-1]+=offset;
5466   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5467   return ret.retn();
5468 }
5469
5470 /*!
5471  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5472  * so that the number of cells remains the same. Quadratic faces are converted to
5473  * polygons. This method works only for 2D meshes in
5474  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5475  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5476  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5477  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5478  *         a polylinized edge constituting the input polygon.
5479  *  \throw If the coordinates array is not set.
5480  *  \throw If the nodal connectivity of cells is not defined.
5481  *  \throw If \a this->getMeshDimension() != 2.
5482  *  \throw If \a this->getSpaceDimension() != 2.
5483  */
5484 void MEDCouplingUMesh::tessellate2D(double eps)
5485 {
5486   checkFullyDefined();
5487   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5488     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5489   double epsa=fabs(eps);
5490   if(epsa<std::numeric_limits<double>::min())
5491     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 !");
5492   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5493   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5494   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5495   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5496   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5497   revDesc1=0; revDescIndx1=0;
5498   mDesc->tessellate2DCurve(eps);
5499   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5500   setCoords(mDesc->getCoords());
5501 }
5502
5503 /*!
5504  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5505  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5506  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5507  *         a sub-divided edge.
5508  *  \throw If the coordinates array is not set.
5509  *  \throw If the nodal connectivity of cells is not defined.
5510  *  \throw If \a this->getMeshDimension() != 1.
5511  *  \throw If \a this->getSpaceDimension() != 2.
5512  */
5513 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5514 {
5515   checkFullyDefined();
5516   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5517     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5518   double epsa=fabs(eps);
5519   if(epsa<std::numeric_limits<double>::min())
5520     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 !");
5521   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5522   int nbCells=getNumberOfCells();
5523   int nbNodes=getNumberOfNodes();
5524   const int *conn=_nodal_connec->getConstPointer();
5525   const int *connI=_nodal_connec_index->getConstPointer();
5526   const double *coords=_coords->getConstPointer();
5527   std::vector<double> addCoo;
5528   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5529   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5530   newConnI->alloc(nbCells+1,1);
5531   int *newConnIPtr=newConnI->getPointer();
5532   *newConnIPtr=0;
5533   int tmp1[3];
5534   INTERP_KERNEL::Node *tmp2[3];
5535   std::set<INTERP_KERNEL::NormalizedCellType> types;
5536   for(int i=0;i<nbCells;i++,newConnIPtr++)
5537     {
5538       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5539       if(cm.isQuadratic())
5540         {//assert(connI[i+1]-connI[i]-1==3)
5541           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5542           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5543           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5544           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5545           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5546           if(eac)
5547             {
5548               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5549               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5550               delete eac;
5551               newConnIPtr[1]=(int)newConn.size();
5552             }
5553           else
5554             {
5555               types.insert(INTERP_KERNEL::NORM_SEG2);
5556               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5557               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5558               newConnIPtr[1]=newConnIPtr[0]+3;
5559             }
5560         }
5561       else
5562         {
5563           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5564           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5565           newConnIPtr[1]=newConnIPtr[0]+3;
5566         }
5567     }
5568   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5569     return ;
5570   _types=types;
5571   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5572   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5573   newConnArr->alloc((int)newConn.size(),1);
5574   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5575   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5576   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5577   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5578   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5579   std::copy(addCoo.begin(),addCoo.end(),work);
5580   DataArrayDouble::SetArrayIn(newCoords,_coords);
5581   updateTime();
5582 }
5583
5584 /*!
5585  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5586  * In addition, returns an array mapping new cells to old ones. <br>
5587  * This method typically increases the number of cells in \a this mesh
5588  * but the number of nodes remains \b unchanged.
5589  * That's why the 3D splitting policies
5590  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5591  *  \param [in] policy - specifies a pattern used for splitting.
5592  * The semantic of \a policy is:
5593  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5594  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5595  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5596  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5597  *
5598  *
5599  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5600  *          an id of old cell producing it. The caller is to delete this array using
5601  *         decrRef() as it is no more needed.
5602  *
5603  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5604  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5605  *          and \a this->getMeshDimension() != 3. 
5606  *  \throw If \a policy is not one of the four discussed above.
5607  *  \throw If the nodal connectivity of cells is not defined.
5608  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5609  */
5610 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5611 {
5612   switch(policy)
5613   {
5614     case 0:
5615       return simplexizePol0();
5616     case 1:
5617       return simplexizePol1();
5618     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5619         return simplexizePlanarFace5();
5620     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5621         return simplexizePlanarFace6();
5622     default:
5623       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)");
5624   }
5625 }
5626
5627 /*!
5628  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5629  * - 1D: INTERP_KERNEL::NORM_SEG2
5630  * - 2D: INTERP_KERNEL::NORM_TRI3
5631  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5632  *
5633  * This method is useful for users that need to use P1 field services as
5634  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5635  * All these methods need mesh support containing only simplex cells.
5636  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5637  *  \throw If the coordinates array is not set.
5638  *  \throw If the nodal connectivity of cells is not defined.
5639  *  \throw If \a this->getMeshDimension() < 1.
5640  */
5641 bool MEDCouplingUMesh::areOnlySimplexCells() const
5642 {
5643   checkFullyDefined();
5644   int mdim=getMeshDimension();
5645   if(mdim<1 || mdim>3)
5646     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5647   int nbCells=getNumberOfCells();
5648   const int *conn=_nodal_connec->getConstPointer();
5649   const int *connI=_nodal_connec_index->getConstPointer();
5650   for(int i=0;i<nbCells;i++)
5651     {
5652       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5653       if(!cm.isSimplex())
5654         return false;
5655     }
5656   return true;
5657 }
5658
5659 /*!
5660  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5661  */
5662 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5663 {
5664   checkConnectivityFullyDefined();
5665   if(getMeshDimension()!=2)
5666     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5667   int nbOfCells=getNumberOfCells();
5668   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5669   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5670   ret->alloc(nbOfCells+nbOfCutCells,1);
5671   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5672   int *retPt=ret->getPointer();
5673   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5674   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5675   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5676   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5677   int *pt=newConn->getPointer();
5678   int *ptI=newConnI->getPointer();
5679   ptI[0]=0;
5680   const int *oldc=_nodal_connec->getConstPointer();
5681   const int *ci=_nodal_connec_index->getConstPointer();
5682   for(int i=0;i<nbOfCells;i++,ci++)
5683     {
5684       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5685         {
5686           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5687             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5688           pt=std::copy(tmp,tmp+8,pt);
5689           ptI[1]=ptI[0]+4;
5690           ptI[2]=ptI[0]+8;
5691           *retPt++=i;
5692           *retPt++=i;
5693           ptI+=2;
5694         }
5695       else
5696         {
5697           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5698           ptI[1]=ptI[0]+ci[1]-ci[0];
5699           ptI++;
5700           *retPt++=i;
5701         }
5702     }
5703   _nodal_connec->decrRef();
5704   _nodal_connec=newConn.retn();
5705   _nodal_connec_index->decrRef();
5706   _nodal_connec_index=newConnI.retn();
5707   computeTypes();
5708   updateTime();
5709   return ret.retn();
5710 }
5711
5712 /*!
5713  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5714  */
5715 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5716 {
5717   checkConnectivityFullyDefined();
5718   if(getMeshDimension()!=2)
5719     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5720   int nbOfCells=getNumberOfCells();
5721   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5722   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5723   ret->alloc(nbOfCells+nbOfCutCells,1);
5724   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5725   int *retPt=ret->getPointer();
5726   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5727   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5728   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5729   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5730   int *pt=newConn->getPointer();
5731   int *ptI=newConnI->getPointer();
5732   ptI[0]=0;
5733   const int *oldc=_nodal_connec->getConstPointer();
5734   const int *ci=_nodal_connec_index->getConstPointer();
5735   for(int i=0;i<nbOfCells;i++,ci++)
5736     {
5737       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5738         {
5739           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5740             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5741           pt=std::copy(tmp,tmp+8,pt);
5742           ptI[1]=ptI[0]+4;
5743           ptI[2]=ptI[0]+8;
5744           *retPt++=i;
5745           *retPt++=i;
5746           ptI+=2;
5747         }
5748       else
5749         {
5750           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5751           ptI[1]=ptI[0]+ci[1]-ci[0];
5752           ptI++;
5753           *retPt++=i;
5754         }
5755     }
5756   _nodal_connec->decrRef();
5757   _nodal_connec=newConn.retn();
5758   _nodal_connec_index->decrRef();
5759   _nodal_connec_index=newConnI.retn();
5760   computeTypes();
5761   updateTime();
5762   return ret.retn();
5763 }
5764
5765 /*!
5766  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5767  */
5768 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5769 {
5770   checkConnectivityFullyDefined();
5771   if(getMeshDimension()!=3)
5772     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5773   int nbOfCells=getNumberOfCells();
5774   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5775   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5776   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5777   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5778   int *retPt=ret->getPointer();
5779   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5780   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5781   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5782   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5783   int *pt=newConn->getPointer();
5784   int *ptI=newConnI->getPointer();
5785   ptI[0]=0;
5786   const int *oldc=_nodal_connec->getConstPointer();
5787   const int *ci=_nodal_connec_index->getConstPointer();
5788   for(int i=0;i<nbOfCells;i++,ci++)
5789     {
5790       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5791         {
5792           for(int j=0;j<5;j++,pt+=5,ptI++)
5793             {
5794               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5795               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];
5796               *retPt++=i;
5797               ptI[1]=ptI[0]+5;
5798             }
5799         }
5800       else
5801         {
5802           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5803           ptI[1]=ptI[0]+ci[1]-ci[0];
5804           ptI++;
5805           *retPt++=i;
5806         }
5807     }
5808   _nodal_connec->decrRef();
5809   _nodal_connec=newConn.retn();
5810   _nodal_connec_index->decrRef();
5811   _nodal_connec_index=newConnI.retn();
5812   computeTypes();
5813   updateTime();
5814   return ret.retn();
5815 }
5816
5817 /*!
5818  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5819  */
5820 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5821 {
5822   checkConnectivityFullyDefined();
5823   if(getMeshDimension()!=3)
5824     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5825   int nbOfCells=getNumberOfCells();
5826   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5827   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5828   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5829   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5830   int *retPt=ret->getPointer();
5831   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5832   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5833   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5834   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5835   int *pt=newConn->getPointer();
5836   int *ptI=newConnI->getPointer();
5837   ptI[0]=0;
5838   const int *oldc=_nodal_connec->getConstPointer();
5839   const int *ci=_nodal_connec_index->getConstPointer();
5840   for(int i=0;i<nbOfCells;i++,ci++)
5841     {
5842       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5843         {
5844           for(int j=0;j<6;j++,pt+=5,ptI++)
5845             {
5846               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5847               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];
5848               *retPt++=i;
5849               ptI[1]=ptI[0]+5;
5850             }
5851         }
5852       else
5853         {
5854           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5855           ptI[1]=ptI[0]+ci[1]-ci[0];
5856           ptI++;
5857           *retPt++=i;
5858         }
5859     }
5860   _nodal_connec->decrRef();
5861   _nodal_connec=newConn.retn();
5862   _nodal_connec_index->decrRef();
5863   _nodal_connec_index=newConnI.retn();
5864   computeTypes();
5865   updateTime();
5866   return ret.retn();
5867 }
5868
5869 /*!
5870  * 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.
5871  * This method completly ignore coordinates.
5872  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5873  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5874  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5875  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5876  */
5877 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5878 {
5879   checkFullyDefined();
5880   if(getMeshDimension()!=2)
5881     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5882   int nbOfCells=getNumberOfCells();
5883   int *connI=_nodal_connec_index->getPointer();
5884   int newConnLgth=0;
5885   for(int i=0;i<nbOfCells;i++,connI++)
5886     {
5887       int offset=descIndex[i];
5888       int nbOfEdges=descIndex[i+1]-offset;
5889       //
5890       bool ddirect=desc[offset+nbOfEdges-1]>0;
5891       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5892       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5893       for(int j=0;j<nbOfEdges;j++)
5894         {
5895           bool direct=desc[offset+j]>0;
5896           int edgeId=std::abs(desc[offset+j])-1;
5897           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5898             {
5899               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5900               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5901               int ref2=direct?id1:id2;
5902               if(ref==ref2)
5903                 {
5904                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5905                   newConnLgth+=nbOfSubNodes-1;
5906                   ref=direct?id2:id1;
5907                 }
5908               else
5909                 {
5910                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5911                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5912                 }
5913             }
5914           else
5915             {
5916               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5917             }
5918         }
5919       newConnLgth++;//+1 is for cell type
5920       connI[1]=newConnLgth;
5921     }
5922   //
5923   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5924   newConn->alloc(newConnLgth,1);
5925   int *work=newConn->getPointer();
5926   for(int i=0;i<nbOfCells;i++)
5927     {
5928       *work++=INTERP_KERNEL::NORM_POLYGON;
5929       int offset=descIndex[i];
5930       int nbOfEdges=descIndex[i+1]-offset;
5931       for(int j=0;j<nbOfEdges;j++)
5932         {
5933           bool direct=desc[offset+j]>0;
5934           int edgeId=std::abs(desc[offset+j])-1;
5935           if(direct)
5936             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5937           else
5938             {
5939               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5940               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5941               work=std::copy(it,it+nbOfSubNodes-1,work);
5942             }
5943         }
5944     }
5945   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5946   _types.clear();
5947   if(nbOfCells>0)
5948     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5949 }
5950
5951 /*!
5952  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5953  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5954  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5955  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5956  * so it can be useful to call mergeNodes() before calling this method.
5957  *  \throw If \a this->getMeshDimension() <= 1.
5958  *  \throw If the coordinates array is not set.
5959  *  \throw If the nodal connectivity of cells is not defined.
5960  */
5961 void MEDCouplingUMesh::convertDegeneratedCells()
5962 {
5963   checkFullyDefined();
5964   if(getMeshDimension()<=1)
5965     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5966   int nbOfCells=getNumberOfCells();
5967   if(nbOfCells<1)
5968     return ;
5969   int initMeshLgth=getMeshLength();
5970   int *conn=_nodal_connec->getPointer();
5971   int *index=_nodal_connec_index->getPointer();
5972   int posOfCurCell=0;
5973   int newPos=0;
5974   int lgthOfCurCell;
5975   for(int i=0;i<nbOfCells;i++)
5976     {
5977       lgthOfCurCell=index[i+1]-posOfCurCell;
5978       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5979       int newLgth;
5980       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5981                                                                                                      conn+newPos+1,newLgth);
5982       conn[newPos]=newType;
5983       newPos+=newLgth+1;
5984       posOfCurCell=index[i+1];
5985       index[i+1]=newPos;
5986     }
5987   if(newPos!=initMeshLgth)
5988     _nodal_connec->reAlloc(newPos);
5989   computeTypes();
5990 }
5991
5992 /*!
5993  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5994  * A cell is considered to be oriented correctly if an angle between its
5995  * normal vector and a given vector is less than \c PI / \c 2.
5996  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5997  *         cells. 
5998  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5999  *         checked.
6000  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6001  *         is not cleared before filling in.
6002  *  \throw If \a this->getMeshDimension() != 2.
6003  *  \throw If \a this->getSpaceDimension() != 3.
6004  *
6005  *  \if ENABLE_EXAMPLES
6006  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6007  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6008  *  \endif
6009  */
6010 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6011 {
6012   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6013     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6014   int nbOfCells=getNumberOfCells();
6015   const int *conn=_nodal_connec->getConstPointer();
6016   const int *connI=_nodal_connec_index->getConstPointer();
6017   const double *coordsPtr=_coords->getConstPointer();
6018   for(int i=0;i<nbOfCells;i++)
6019     {
6020       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6021       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6022         {
6023           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6024           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6025             cells.push_back(i);
6026         }
6027     }
6028 }
6029
6030 /*!
6031  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6032  * considered to be oriented correctly if an angle between its normal vector and a
6033  * given vector is less than \c PI / \c 2. 
6034  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6035  *         cells. 
6036  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6037  *         checked.
6038  *  \throw If \a this->getMeshDimension() != 2.
6039  *  \throw If \a this->getSpaceDimension() != 3.
6040  *
6041  *  \if ENABLE_EXAMPLES
6042  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6043  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6044  *  \endif
6045  *
6046  *  \sa changeOrientationOfCells
6047  */
6048 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6049 {
6050   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6051     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6052   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6053   const int *connI(_nodal_connec_index->getConstPointer());
6054   const double *coordsPtr(_coords->getConstPointer());
6055   bool isModified(false);
6056   for(int i=0;i<nbOfCells;i++)
6057     {
6058       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6059       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6060         {
6061           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6062           bool isQuadratic(cm.isQuadratic());
6063           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6064             {
6065               isModified=true;
6066               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6067             }
6068         }
6069     }
6070   if(isModified)
6071     _nodal_connec->declareAsNew();
6072   updateTime();
6073 }
6074
6075 /*!
6076  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6077  *
6078  * \sa orientCorrectly2DCells
6079  */
6080 void MEDCouplingUMesh::changeOrientationOfCells()
6081 {
6082   int mdim(getMeshDimension());
6083   if(mdim!=2 && mdim!=1)
6084     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6085   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6086   const int *connI(_nodal_connec_index->getConstPointer());
6087   if(mdim==2)
6088     {//2D
6089       for(int i=0;i<nbOfCells;i++)
6090         {
6091           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6092           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6093           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6094         }
6095     }
6096   else
6097     {//1D
6098       for(int i=0;i<nbOfCells;i++)
6099         {
6100           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6101           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6102           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6103         }
6104     }
6105 }
6106
6107 /*!
6108  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6109  * oriented facets. The normal vector of the facet should point out of the cell.
6110  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6111  *         is not cleared before filling in.
6112  *  \throw If \a this->getMeshDimension() != 3.
6113  *  \throw If \a this->getSpaceDimension() != 3.
6114  *  \throw If the coordinates array is not set.
6115  *  \throw If the nodal connectivity of cells is not defined.
6116  *
6117  *  \if ENABLE_EXAMPLES
6118  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6119  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6120  *  \endif
6121  */
6122 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6123 {
6124   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6125     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6126   int nbOfCells=getNumberOfCells();
6127   const int *conn=_nodal_connec->getConstPointer();
6128   const int *connI=_nodal_connec_index->getConstPointer();
6129   const double *coordsPtr=_coords->getConstPointer();
6130   for(int i=0;i<nbOfCells;i++)
6131     {
6132       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6133       if(type==INTERP_KERNEL::NORM_POLYHED)
6134         {
6135           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6136             cells.push_back(i);
6137         }
6138     }
6139 }
6140
6141 /*!
6142  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6143  * out of the cell. 
6144  *  \throw If \a this->getMeshDimension() != 3.
6145  *  \throw If \a this->getSpaceDimension() != 3.
6146  *  \throw If the coordinates array is not set.
6147  *  \throw If the nodal connectivity of cells is not defined.
6148  *  \throw If the reparation fails.
6149  *
6150  *  \if ENABLE_EXAMPLES
6151  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6152  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6153  *  \endif
6154  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6155  */
6156 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6157 {
6158   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6159     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6160   int nbOfCells=getNumberOfCells();
6161   int *conn=_nodal_connec->getPointer();
6162   const int *connI=_nodal_connec_index->getConstPointer();
6163   const double *coordsPtr=_coords->getConstPointer();
6164   for(int i=0;i<nbOfCells;i++)
6165     {
6166       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6167       if(type==INTERP_KERNEL::NORM_POLYHED)
6168         {
6169           try
6170           {
6171               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6172                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6173           }
6174           catch(INTERP_KERNEL::Exception& e)
6175           {
6176               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6177               throw INTERP_KERNEL::Exception(oss.str().c_str());
6178           }
6179         }
6180     }
6181   updateTime();
6182 }
6183
6184 /*!
6185  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6186  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6187  * according to which the first facet of the cell should be oriented to have the normal vector
6188  * pointing out of cell.
6189  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6190  *         cells. The caller is to delete this array using decrRef() as it is no more
6191  *         needed. 
6192  *  \throw If \a this->getMeshDimension() != 3.
6193  *  \throw If \a this->getSpaceDimension() != 3.
6194  *  \throw If the coordinates array is not set.
6195  *  \throw If the nodal connectivity of cells is not defined.
6196  *
6197  *  \if ENABLE_EXAMPLES
6198  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6199  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6200  *  \endif
6201  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6202  */
6203 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6204 {
6205   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6206   if(getMeshDimension()!=3)
6207     throw INTERP_KERNEL::Exception(msg);
6208   int spaceDim=getSpaceDimension();
6209   if(spaceDim!=3)
6210     throw INTERP_KERNEL::Exception(msg);
6211   //
6212   int nbOfCells=getNumberOfCells();
6213   int *conn=_nodal_connec->getPointer();
6214   const int *connI=_nodal_connec_index->getConstPointer();
6215   const double *coo=getCoords()->getConstPointer();
6216   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6217   for(int i=0;i<nbOfCells;i++)
6218     {
6219       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6220       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6221         {
6222           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6223             {
6224               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6225               cells->pushBackSilent(i);
6226             }
6227         }
6228     }
6229   return cells.retn();
6230 }
6231
6232 /*!
6233  * This method is a faster method to correct orientation of all 3D cells in \a this.
6234  * 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.
6235  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6236  * 
6237  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6238  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6239  */
6240 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6241 {
6242   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6243     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6244   int nbOfCells=getNumberOfCells();
6245   int *conn=_nodal_connec->getPointer();
6246   const int *connI=_nodal_connec_index->getConstPointer();
6247   const double *coordsPtr=_coords->getConstPointer();
6248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6249   for(int i=0;i<nbOfCells;i++)
6250     {
6251       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6252       switch(type)
6253       {
6254         case INTERP_KERNEL::NORM_TETRA4:
6255           {
6256             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6257               {
6258                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6259                 ret->pushBackSilent(i);
6260               }
6261             break;
6262           }
6263         case INTERP_KERNEL::NORM_PYRA5:
6264           {
6265             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6266               {
6267                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6268                 ret->pushBackSilent(i);
6269               }
6270             break;
6271           }
6272         case INTERP_KERNEL::NORM_PENTA6:
6273         case INTERP_KERNEL::NORM_HEXA8:
6274         case INTERP_KERNEL::NORM_HEXGP12:
6275           {
6276             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6277               {
6278                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6279                 ret->pushBackSilent(i);
6280               }
6281             break;
6282           }
6283         case INTERP_KERNEL::NORM_POLYHED:
6284           {
6285             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6286               {
6287                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6288                 ret->pushBackSilent(i);
6289               }
6290             break;
6291           }
6292         default:
6293           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 !");
6294       }
6295     }
6296   updateTime();
6297   return ret.retn();
6298 }
6299
6300 /*!
6301  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6302  * If it is not the case an exception will be thrown.
6303  * This method is fast because the first cell of \a this is used to compute the plane.
6304  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6305  * \param pos output of size at least 3 used to store a point owned of searched plane.
6306  */
6307 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6308 {
6309   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6310     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6311   const int *conn=_nodal_connec->getConstPointer();
6312   const int *connI=_nodal_connec_index->getConstPointer();
6313   const double *coordsPtr=_coords->getConstPointer();
6314   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6315   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6316 }
6317
6318 /*!
6319  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6320  * cells. Currently cells of the following types are treated:
6321  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6322  * For a cell of other type an exception is thrown.
6323  * Space dimension of a 2D mesh can be either 2 or 3.
6324  * The Edge Ratio of a cell \f$t\f$ is: 
6325  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6326  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6327  *  the smallest edge lengths of \f$t\f$.
6328  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6329  *          cells and one time, lying on \a this mesh. The caller is to delete this
6330  *          field using decrRef() as it is no more needed. 
6331  *  \throw If the coordinates array is not set.
6332  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6333  *  \throw If the connectivity data array has more than one component.
6334  *  \throw If the connectivity data array has a named component.
6335  *  \throw If the connectivity index data array has more than one component.
6336  *  \throw If the connectivity index data array has a named component.
6337  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6338  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6339  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6340  */
6341 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6342 {
6343   checkCoherency();
6344   int spaceDim=getSpaceDimension();
6345   int meshDim=getMeshDimension();
6346   if(spaceDim!=2 && spaceDim!=3)
6347     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6348   if(meshDim!=2 && meshDim!=3)
6349     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6350   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6351   ret->setMesh(this);
6352   int nbOfCells=getNumberOfCells();
6353   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6354   arr->alloc(nbOfCells,1);
6355   double *pt=arr->getPointer();
6356   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6357   const int *conn=_nodal_connec->getConstPointer();
6358   const int *connI=_nodal_connec_index->getConstPointer();
6359   const double *coo=_coords->getConstPointer();
6360   double tmp[12];
6361   for(int i=0;i<nbOfCells;i++,pt++)
6362     {
6363       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6364       switch(t)
6365       {
6366         case INTERP_KERNEL::NORM_TRI3:
6367           {
6368             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6369             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6370             break;
6371           }
6372         case INTERP_KERNEL::NORM_QUAD4:
6373           {
6374             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6375             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6376             break;
6377           }
6378         case INTERP_KERNEL::NORM_TETRA4:
6379           {
6380             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6381             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6382             break;
6383           }
6384         default:
6385           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6386       }
6387       conn+=connI[i+1]-connI[i];
6388     }
6389   ret->setName("EdgeRatio");
6390   ret->synchronizeTimeWithSupport();
6391   return ret.retn();
6392 }
6393
6394 /*!
6395  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6396  * cells. Currently cells of the following types are treated:
6397  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6398  * For a cell of other type an exception is thrown.
6399  * Space dimension of a 2D mesh can be either 2 or 3.
6400  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6401  *          cells and one time, lying on \a this mesh. The caller is to delete this
6402  *          field using decrRef() as it is no more needed. 
6403  *  \throw If the coordinates array is not set.
6404  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6405  *  \throw If the connectivity data array has more than one component.
6406  *  \throw If the connectivity data array has a named component.
6407  *  \throw If the connectivity index data array has more than one component.
6408  *  \throw If the connectivity index data array has a named component.
6409  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6410  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6411  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6412  */
6413 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6414 {
6415   checkCoherency();
6416   int spaceDim=getSpaceDimension();
6417   int meshDim=getMeshDimension();
6418   if(spaceDim!=2 && spaceDim!=3)
6419     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6420   if(meshDim!=2 && meshDim!=3)
6421     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6422   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6423   ret->setMesh(this);
6424   int nbOfCells=getNumberOfCells();
6425   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6426   arr->alloc(nbOfCells,1);
6427   double *pt=arr->getPointer();
6428   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6429   const int *conn=_nodal_connec->getConstPointer();
6430   const int *connI=_nodal_connec_index->getConstPointer();
6431   const double *coo=_coords->getConstPointer();
6432   double tmp[12];
6433   for(int i=0;i<nbOfCells;i++,pt++)
6434     {
6435       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6436       switch(t)
6437       {
6438         case INTERP_KERNEL::NORM_TRI3:
6439           {
6440             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6441             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6442             break;
6443           }
6444         case INTERP_KERNEL::NORM_QUAD4:
6445           {
6446             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6447             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6448             break;
6449           }
6450         case INTERP_KERNEL::NORM_TETRA4:
6451           {
6452             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6453             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6454             break;
6455           }
6456         default:
6457           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6458       }
6459       conn+=connI[i+1]-connI[i];
6460     }
6461   ret->setName("AspectRatio");
6462   ret->synchronizeTimeWithSupport();
6463   return ret.retn();
6464 }
6465
6466 /*!
6467  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6468  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6469  * treated: INTERP_KERNEL::NORM_QUAD4.
6470  * For a cell of other type an exception is thrown.
6471  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6472  *          cells and one time, lying on \a this mesh. The caller is to delete this
6473  *          field using decrRef() as it is no more needed. 
6474  *  \throw If the coordinates array is not set.
6475  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6476  *  \throw If the connectivity data array has more than one component.
6477  *  \throw If the connectivity data array has a named component.
6478  *  \throw If the connectivity index data array has more than one component.
6479  *  \throw If the connectivity index data array has a named component.
6480  *  \throw If \a this->getMeshDimension() != 2.
6481  *  \throw If \a this->getSpaceDimension() != 3.
6482  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6483  */
6484 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6485 {
6486   checkCoherency();
6487   int spaceDim=getSpaceDimension();
6488   int meshDim=getMeshDimension();
6489   if(spaceDim!=3)
6490     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6491   if(meshDim!=2)
6492     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6493   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6494   ret->setMesh(this);
6495   int nbOfCells=getNumberOfCells();
6496   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6497   arr->alloc(nbOfCells,1);
6498   double *pt=arr->getPointer();
6499   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6500   const int *conn=_nodal_connec->getConstPointer();
6501   const int *connI=_nodal_connec_index->getConstPointer();
6502   const double *coo=_coords->getConstPointer();
6503   double tmp[12];
6504   for(int i=0;i<nbOfCells;i++,pt++)
6505     {
6506       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6507       switch(t)
6508       {
6509         case INTERP_KERNEL::NORM_QUAD4:
6510           {
6511             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6512             *pt=INTERP_KERNEL::quadWarp(tmp);
6513             break;
6514           }
6515         default:
6516           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6517       }
6518       conn+=connI[i+1]-connI[i];
6519     }
6520   ret->setName("Warp");
6521   ret->synchronizeTimeWithSupport();
6522   return ret.retn();
6523 }
6524
6525
6526 /*!
6527  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6528  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6529  * treated: INTERP_KERNEL::NORM_QUAD4.
6530  * For a cell of other type an exception is thrown.
6531  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6532  *          cells and one time, lying on \a this mesh. The caller is to delete this
6533  *          field using decrRef() as it is no more needed. 
6534  *  \throw If the coordinates array is not set.
6535  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6536  *  \throw If the connectivity data array has more than one component.
6537  *  \throw If the connectivity data array has a named component.
6538  *  \throw If the connectivity index data array has more than one component.
6539  *  \throw If the connectivity index data array has a named component.
6540  *  \throw If \a this->getMeshDimension() != 2.
6541  *  \throw If \a this->getSpaceDimension() != 3.
6542  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6543  */
6544 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6545 {
6546   checkCoherency();
6547   int spaceDim=getSpaceDimension();
6548   int meshDim=getMeshDimension();
6549   if(spaceDim!=3)
6550     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6551   if(meshDim!=2)
6552     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6553   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6554   ret->setMesh(this);
6555   int nbOfCells=getNumberOfCells();
6556   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6557   arr->alloc(nbOfCells,1);
6558   double *pt=arr->getPointer();
6559   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6560   const int *conn=_nodal_connec->getConstPointer();
6561   const int *connI=_nodal_connec_index->getConstPointer();
6562   const double *coo=_coords->getConstPointer();
6563   double tmp[12];
6564   for(int i=0;i<nbOfCells;i++,pt++)
6565     {
6566       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6567       switch(t)
6568       {
6569         case INTERP_KERNEL::NORM_QUAD4:
6570           {
6571             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6572             *pt=INTERP_KERNEL::quadSkew(tmp);
6573             break;
6574           }
6575         default:
6576           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6577       }
6578       conn+=connI[i+1]-connI[i];
6579     }
6580   ret->setName("Skew");
6581   ret->synchronizeTimeWithSupport();
6582   return ret.retn();
6583 }
6584
6585 /*!
6586  * 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.
6587  *
6588  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6589  *
6590  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6591  */
6592 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6593 {
6594   checkCoherency();
6595   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6596   ret->setMesh(this);
6597   std::set<INTERP_KERNEL::NormalizedCellType> types;
6598   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6599   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6600   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6601   arr->alloc(nbCells,1);
6602   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6603     {
6604       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6605       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6606       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6607     }
6608   ret->setArray(arr);
6609   ret->setName("Diameter");
6610   return ret.retn();
6611 }
6612
6613 /*!
6614  * This method aggregate the bbox of each cell and put it into bbox parameter.
6615  * 
6616  * \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)
6617  *                         For all other cases this input parameter is ignored.
6618  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6619  * 
6620  * \throw If \a this is not fully set (coordinates and connectivity).
6621  * \throw If a cell in \a this has no valid nodeId.
6622  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6623  */
6624 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6625 {
6626   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6627   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.
6628     return getBoundingBoxForBBTreeFast();
6629   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6630     {
6631       bool presenceOfQuadratic(false);
6632       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6633         {
6634           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6635           if(cm.isQuadratic())
6636             presenceOfQuadratic=true;
6637         }
6638       if(!presenceOfQuadratic)
6639         return getBoundingBoxForBBTreeFast();
6640       if(mDim==2 && sDim==2)
6641         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6642       else
6643         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6644     }
6645   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) !");
6646 }
6647
6648 /*!
6649  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6650  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6651  * 
6652  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6653  * 
6654  * \throw If \a this is not fully set (coordinates and connectivity).
6655  * \throw If a cell in \a this has no valid nodeId.
6656  */
6657 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6658 {
6659   checkFullyDefined();
6660   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6661   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6662   double *bbox(ret->getPointer());
6663   for(int i=0;i<nbOfCells*spaceDim;i++)
6664     {
6665       bbox[2*i]=std::numeric_limits<double>::max();
6666       bbox[2*i+1]=-std::numeric_limits<double>::max();
6667     }
6668   const double *coordsPtr(_coords->getConstPointer());
6669   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6670   for(int i=0;i<nbOfCells;i++)
6671     {
6672       int offset=connI[i]+1;
6673       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6674       for(int j=0;j<nbOfNodesForCell;j++)
6675         {
6676           int nodeId=conn[offset+j];
6677           if(nodeId>=0 && nodeId<nbOfNodes)
6678             {
6679               for(int k=0;k<spaceDim;k++)
6680                 {
6681                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6682                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6683                 }
6684               kk++;
6685             }
6686         }
6687       if(kk==0)
6688         {
6689           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6690           throw INTERP_KERNEL::Exception(oss.str().c_str());
6691         }
6692     }
6693   return ret.retn();
6694 }
6695
6696 /*!
6697  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6698  * useful for 2D meshes having quadratic cells
6699  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6700  * the two extremities of the arc of circle).
6701  * 
6702  * \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)
6703  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6704  * \throw If \a this is not fully defined.
6705  * \throw If \a this is not a mesh with meshDimension equal to 2.
6706  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6707  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6708  */
6709 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6710 {
6711   checkFullyDefined();
6712   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6713   if(spaceDim!=2 || mDim!=2)
6714     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!");
6715   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6716   double *bbox(ret->getPointer());
6717   const double *coords(_coords->getConstPointer());
6718   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6719   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6720     {
6721       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6722       int sz(connI[1]-connI[0]-1);
6723       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6724       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6725       INTERP_KERNEL::QuadraticPolygon *pol(0);
6726       for(int j=0;j<sz;j++)
6727         {
6728           int nodeId(conn[*connI+1+j]);
6729           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6730         }
6731       if(!cm.isQuadratic())
6732         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6733       else
6734         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6735       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6736       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6737     }
6738   return ret.retn();
6739 }
6740
6741 /*!
6742  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6743  * useful for 2D meshes having quadratic cells
6744  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6745  * the two extremities of the arc of circle).
6746  * 
6747  * \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)
6748  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6749  * \throw If \a this is not fully defined.
6750  * \throw If \a this is not a mesh with meshDimension equal to 1.
6751  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6752  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6753  */
6754 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6755 {
6756   checkFullyDefined();
6757   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6758   if(spaceDim!=2 || mDim!=1)
6759     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!");
6760   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6761   double *bbox(ret->getPointer());
6762   const double *coords(_coords->getConstPointer());
6763   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6764   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6765     {
6766       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6767       int sz(connI[1]-connI[0]-1);
6768       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6769       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6770       INTERP_KERNEL::Edge *edge(0);
6771       for(int j=0;j<sz;j++)
6772         {
6773           int nodeId(conn[*connI+1+j]);
6774           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6775         }
6776       if(!cm.isQuadratic())
6777         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6778       else
6779         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6780       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6781       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6782     }
6783   return ret.retn();
6784 }
6785
6786 /// @cond INTERNAL
6787
6788 namespace ParaMEDMEMImpl
6789 {
6790   class ConnReader
6791   {
6792   public:
6793     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6794     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6795   private:
6796     const int *_conn;
6797     int _val;
6798   };
6799
6800   class ConnReader2
6801   {
6802   public:
6803     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6804     bool operator() (const int& pos) { return _conn[pos]==_val; }
6805   private:
6806     const int *_conn;
6807     int _val;
6808   };
6809 }
6810
6811 /// @endcond
6812
6813 /*!
6814  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6815  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6816  * \a this is composed in cell types.
6817  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6818  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6819  * This parameter is kept only for compatibility with other methode listed above.
6820  */
6821 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6822 {
6823   checkConnectivityFullyDefined();
6824   const int *conn=_nodal_connec->getConstPointer();
6825   const int *connI=_nodal_connec_index->getConstPointer();
6826   const int *work=connI;
6827   int nbOfCells=getNumberOfCells();
6828   std::size_t n=getAllGeoTypes().size();
6829   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6830   std::set<INTERP_KERNEL::NormalizedCellType> types;
6831   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6832     {
6833       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6834       if(types.find(typ)!=types.end())
6835         {
6836           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6837           oss << " is not contiguous !";
6838           throw INTERP_KERNEL::Exception(oss.str().c_str());
6839         }
6840       types.insert(typ);
6841       ret[3*i]=typ;
6842       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6843       ret[3*i+1]=(int)std::distance(work,work2);
6844       work=work2;
6845     }
6846   return ret;
6847 }
6848
6849 /*!
6850  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6851  * only for types cell, type node is not managed.
6852  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6853  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6854  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6855  * If 2 or more same geometric type is in \a code and exception is thrown too.
6856  *
6857  * This method firstly checks
6858  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6859  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6860  * an exception is thrown too.
6861  * 
6862  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6863  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6864  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6865  */
6866 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6867 {
6868   if(code.empty())
6869     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6870   std::size_t sz=code.size();
6871   std::size_t n=sz/3;
6872   if(sz%3!=0)
6873     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6874   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6875   int nb=0;
6876   bool isNoPflUsed=true;
6877   for(std::size_t i=0;i<n;i++)
6878     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6879       {
6880         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6881         nb+=code[3*i+1];
6882         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6883           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6884         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6885       }
6886   if(types.size()!=n)
6887     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6888   if(isNoPflUsed)
6889     {
6890       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6891         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6892       if(types.size()==_types.size())
6893         return 0;
6894     }
6895   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6896   ret->alloc(nb,1);
6897   int *retPtr=ret->getPointer();
6898   const int *connI=_nodal_connec_index->getConstPointer();
6899   const int *conn=_nodal_connec->getConstPointer();
6900   int nbOfCells=getNumberOfCells();
6901   const int *i=connI;
6902   int kk=0;
6903   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6904     {
6905       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6906       int offset=(int)std::distance(connI,i);
6907       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6908       int nbOfCellsOfCurType=(int)std::distance(i,j);
6909       if(code[3*kk+2]==-1)
6910         for(int k=0;k<nbOfCellsOfCurType;k++)
6911           *retPtr++=k+offset;
6912       else
6913         {
6914           int idInIdsPerType=code[3*kk+2];
6915           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6916             {
6917               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6918               if(zePfl)
6919                 {
6920                   zePfl->checkAllocated();
6921                   if(zePfl->getNumberOfComponents()==1)
6922                     {
6923                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6924                         {
6925                           if(*k>=0 && *k<nbOfCellsOfCurType)
6926                             *retPtr=(*k)+offset;
6927                           else
6928                             {
6929                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6930                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6931                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6932                             }
6933                         }
6934                     }
6935                   else
6936                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6937                 }
6938               else
6939                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6940             }
6941           else
6942             {
6943               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6944               oss << " should be in [0," << idsPerType.size() << ") !";
6945               throw INTERP_KERNEL::Exception(oss.str().c_str());
6946             }
6947         }
6948       i=j;
6949     }
6950   return ret.retn();
6951 }
6952
6953 /*!
6954  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
6955  * 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.
6956  * 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.
6957  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6958  * 
6959  * \param [in] profile
6960  * \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.
6961  * \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,
6962  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6963  * \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.
6964  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6965  * \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
6966  */
6967 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6968 {
6969   if(!profile)
6970     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6971   if(profile->getNumberOfComponents()!=1)
6972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6973   checkConnectivityFullyDefined();
6974   const int *conn=_nodal_connec->getConstPointer();
6975   const int *connI=_nodal_connec_index->getConstPointer();
6976   int nbOfCells=getNumberOfCells();
6977   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6978   std::vector<int> typeRangeVals(1);
6979   for(const int *i=connI;i!=connI+nbOfCells;)
6980     {
6981       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6982       if(std::find(types.begin(),types.end(),curType)!=types.end())
6983         {
6984           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6985         }
6986       types.push_back(curType);
6987       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6988       typeRangeVals.push_back((int)std::distance(connI,i));
6989     }
6990   //
6991   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6992   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6993   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6994   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6995   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6996   //
6997   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6998   code.resize(3*nbOfCastsFinal);
6999   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
7000   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
7001   for(int i=0;i<nbOfCastsFinal;i++)
7002     {
7003       int castId=castsPresent->getIJ(i,0);
7004       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
7005       idsInPflPerType2.push_back(tmp3);
7006       code[3*i]=(int)types[castId];
7007       code[3*i+1]=tmp3->getNumberOfTuples();
7008       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7009       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
7010         {
7011           tmp4->copyStringInfoFrom(*profile);
7012           idsPerType2.push_back(tmp4);
7013           code[3*i+2]=(int)idsPerType2.size()-1;
7014         }
7015       else
7016         {
7017           code[3*i+2]=-1;
7018         }
7019     }
7020   std::size_t sz2=idsInPflPerType2.size();
7021   idsInPflPerType.resize(sz2);
7022   for(std::size_t i=0;i<sz2;i++)
7023     {
7024       DataArrayInt *locDa=idsInPflPerType2[i];
7025       locDa->incrRef();
7026       idsInPflPerType[i]=locDa;
7027     }
7028   std::size_t sz=idsPerType2.size();
7029   idsPerType.resize(sz);
7030   for(std::size_t i=0;i<sz;i++)
7031     {
7032       DataArrayInt *locDa=idsPerType2[i];
7033       locDa->incrRef();
7034       idsPerType[i]=locDa;
7035     }
7036 }
7037
7038 /*!
7039  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7040  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7041  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7042  * 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.
7043  */
7044 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7045 {
7046   checkFullyDefined();
7047   nM1LevMesh->checkFullyDefined();
7048   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7049     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7050   if(_coords!=nM1LevMesh->getCoords())
7051     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7052   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7053   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7054   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7055   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7056   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7057   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7058   tmp->setConnectivity(tmp0,tmp1);
7059   tmp->renumberCells(ret0->getConstPointer(),false);
7060   revDesc=tmp->getNodalConnectivity();
7061   revDescIndx=tmp->getNodalConnectivityIndex();
7062   DataArrayInt *ret=0;
7063   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7064     {
7065       int tmp2;
7066       ret->getMaxValue(tmp2);
7067       ret->decrRef();
7068       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7069       throw INTERP_KERNEL::Exception(oss.str().c_str());
7070     }
7071   nM1LevMeshIds=ret;
7072   //
7073   revDesc->incrRef();
7074   revDescIndx->incrRef();
7075   ret1->incrRef();
7076   ret0->incrRef();
7077   meshnM1Old2New=ret0;
7078   return ret1;
7079 }
7080
7081 /*!
7082  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7083  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7084  * in "Old to New" mode.
7085  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7086  *          this array using decrRef() as it is no more needed.
7087  *  \throw If the nodal connectivity of cells is not defined.
7088  */
7089 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7090 {
7091   checkConnectivityFullyDefined();
7092   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7093   renumberCells(ret->getConstPointer(),false);
7094   return ret.retn();
7095 }
7096
7097 /*!
7098  * This methods checks that cells are sorted by their types.
7099  * This method makes asumption (no check) that connectivity is correctly set before calling.
7100  */
7101 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7102 {
7103   checkFullyDefined();
7104   const int *conn=_nodal_connec->getConstPointer();
7105   const int *connI=_nodal_connec_index->getConstPointer();
7106   int nbOfCells=getNumberOfCells();
7107   std::set<INTERP_KERNEL::NormalizedCellType> types;
7108   for(const int *i=connI;i!=connI+nbOfCells;)
7109     {
7110       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7111       if(types.find(curType)!=types.end())
7112         return false;
7113       types.insert(curType);
7114       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7115     }
7116   return true;
7117 }
7118
7119 /*!
7120  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7121  * The geometric type order is specified by MED file.
7122  * 
7123  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7124  */
7125 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7126 {
7127   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7128 }
7129
7130 /*!
7131  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7132  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7133  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7134  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7135  */
7136 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7137 {
7138   checkFullyDefined();
7139   const int *conn=_nodal_connec->getConstPointer();
7140   const int *connI=_nodal_connec_index->getConstPointer();
7141   int nbOfCells=getNumberOfCells();
7142   if(nbOfCells==0)
7143     return true;
7144   int lastPos=-1;
7145   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7146   for(const int *i=connI;i!=connI+nbOfCells;)
7147     {
7148       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7149       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7150       if(isTypeExists!=orderEnd)
7151         {
7152           int pos=(int)std::distance(orderBg,isTypeExists);
7153           if(pos<=lastPos)
7154             return false;
7155           lastPos=pos;
7156           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7157         }
7158       else
7159         {
7160           if(sg.find(curType)==sg.end())
7161             {
7162               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7163               sg.insert(curType);
7164             }
7165           else
7166             return false;
7167         }
7168     }
7169   return true;
7170 }
7171
7172 /*!
7173  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7174  * 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
7175  * 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'.
7176  */
7177 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7178 {
7179   checkConnectivityFullyDefined();
7180   int nbOfCells=getNumberOfCells();
7181   const int *conn=_nodal_connec->getConstPointer();
7182   const int *connI=_nodal_connec_index->getConstPointer();
7183   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7184   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7185   tmpa->alloc(nbOfCells,1);
7186   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7187   tmpb->fillWithZero();
7188   int *tmp=tmpa->getPointer();
7189   int *tmp2=tmpb->getPointer();
7190   for(const int *i=connI;i!=connI+nbOfCells;i++)
7191     {
7192       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7193       if(where!=orderEnd)
7194         {
7195           int pos=(int)std::distance(orderBg,where);
7196           tmp2[pos]++;
7197           tmp[std::distance(connI,i)]=pos;
7198         }
7199       else
7200         {
7201           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7202           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7203           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7204           throw INTERP_KERNEL::Exception(oss.str().c_str());
7205         }
7206     }
7207   nbPerType=tmpb.retn();
7208   return tmpa.retn();
7209 }
7210
7211 /*!
7212  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7213  *
7214  * \return a new object containing the old to new correspondance.
7215  *
7216  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7217  */
7218 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7219 {
7220   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7221 }
7222
7223 /*!
7224  * 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.
7225  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7226  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7227  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7228  */
7229 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7230 {
7231   DataArrayInt *nbPerType=0;
7232   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7233   nbPerType->decrRef();
7234   return tmpa->buildPermArrPerLevel();
7235 }
7236
7237 /*!
7238  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7239  * The number of cells remains unchanged after the call of this method.
7240  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7241  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7242  *
7243  * \return the array giving the correspondance old to new.
7244  */
7245 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7246 {
7247   checkFullyDefined();
7248   computeTypes();
7249   const int *conn=_nodal_connec->getConstPointer();
7250   const int *connI=_nodal_connec_index->getConstPointer();
7251   int nbOfCells=getNumberOfCells();
7252   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7253   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7254     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7255       {
7256         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7257         types.push_back(curType);
7258         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7259       }
7260   DataArrayInt *ret=DataArrayInt::New();
7261   ret->alloc(nbOfCells,1);
7262   int *retPtr=ret->getPointer();
7263   std::fill(retPtr,retPtr+nbOfCells,-1);
7264   int newCellId=0;
7265   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7266     {
7267       for(const int *i=connI;i!=connI+nbOfCells;i++)
7268         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7269           retPtr[std::distance(connI,i)]=newCellId++;
7270     }
7271   renumberCells(retPtr,false);
7272   return ret;
7273 }
7274
7275 /*!
7276  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7277  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7278  * This method makes asumption that connectivity is correctly set before calling.
7279  */
7280 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7281 {
7282   checkConnectivityFullyDefined();
7283   const int *conn=_nodal_connec->getConstPointer();
7284   const int *connI=_nodal_connec_index->getConstPointer();
7285   int nbOfCells=getNumberOfCells();
7286   std::vector<MEDCouplingUMesh *> ret;
7287   for(const int *i=connI;i!=connI+nbOfCells;)
7288     {
7289       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7290       int beginCellId=(int)std::distance(connI,i);
7291       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7292       int endCellId=(int)std::distance(connI,i);
7293       int sz=endCellId-beginCellId;
7294       int *cells=new int[sz];
7295       for(int j=0;j<sz;j++)
7296         cells[j]=beginCellId+j;
7297       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7298       delete [] cells;
7299       ret.push_back(m);
7300     }
7301   return ret;
7302 }
7303
7304 /*!
7305  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7306  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7307  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7308  *
7309  * \return a newly allocated instance, that the caller must manage.
7310  * \throw If \a this contains more than one geometric type.
7311  * \throw If the nodal connectivity of \a this is not fully defined.
7312  * \throw If the internal data is not coherent.
7313  */
7314 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7315 {
7316   checkConnectivityFullyDefined();
7317   if(_types.size()!=1)
7318     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7319   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7320   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7321   ret->setCoords(getCoords());
7322   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7323   if(retC)
7324     {
7325       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7326       retC->setNodalConnectivity(c);
7327     }
7328   else
7329     {
7330       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7331       if(!retD)
7332         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7333       DataArrayInt *c=0,*ci=0;
7334       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7335       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7336       retD->setNodalConnectivity(cs,cis);
7337     }
7338   return ret.retn();
7339 }
7340
7341 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7342 {
7343   checkConnectivityFullyDefined();
7344   if(_types.size()!=1)
7345     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7346   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7347   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7348   if(cm.isDynamic())
7349     {
7350       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7351       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7352       throw INTERP_KERNEL::Exception(oss.str().c_str());
7353     }
7354   int nbCells=getNumberOfCells();
7355   int typi=(int)typ;
7356   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7357   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7358   int *outPtr=connOut->getPointer();
7359   const int *conn=_nodal_connec->begin();
7360   const int *connI=_nodal_connec_index->begin();
7361   nbNodesPerCell++;
7362   for(int i=0;i<nbCells;i++,connI++)
7363     {
7364       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7365         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7366       else
7367         {
7368           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 << ") !";
7369           throw INTERP_KERNEL::Exception(oss.str().c_str());
7370         }
7371     }
7372   return connOut.retn();
7373 }
7374
7375 /*!
7376  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7377  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7378  * \param nodalConn
7379  * \param nodalConnI
7380  */
7381 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7382 {
7383   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7384   checkConnectivityFullyDefined();
7385   if(_types.size()!=1)
7386     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7387   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7388   if(lgth<nbCells)
7389     throw INTERP_KERNEL::Exception(msg0);
7390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7391   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7392   int *cp(c->getPointer()),*cip(ci->getPointer());
7393   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7394   cip[0]=0;
7395   for(int i=0;i<nbCells;i++,cip++,incip++)
7396     {
7397       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7398       int delta(stop-strt);
7399       if(delta>=1)
7400         {
7401           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7402             cp=std::copy(incp+strt,incp+stop,cp);
7403           else
7404             throw INTERP_KERNEL::Exception(msg0);
7405         }
7406       else
7407         throw INTERP_KERNEL::Exception(msg0);
7408       cip[1]=cip[0]+delta;
7409     }
7410   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7411 }
7412
7413 /*!
7414  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7415  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7416  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7417  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7418  * are not used here to avoid the build of big permutation array.
7419  *
7420  * \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
7421  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7422  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7423  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7424  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7425  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7426  * \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
7427  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7428  */
7429 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7430                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7431                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7432 {
7433   std::vector<const MEDCouplingUMesh *> ms2;
7434   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7435     if(*it)
7436       {
7437         (*it)->checkConnectivityFullyDefined();
7438         ms2.push_back(*it);
7439       }
7440   if(ms2.empty())
7441     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7442   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7443   int meshDim=ms2[0]->getMeshDimension();
7444   std::vector<const MEDCouplingUMesh *> m1ssm;
7445   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7446   //
7447   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7448   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7449   int fake=0,rk=0;
7450   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7451   ret1->alloc(0,1); ret2->alloc(0,1);
7452   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7453     {
7454       if(meshDim!=(*it)->getMeshDimension())
7455         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7456       if(refCoo!=(*it)->getCoords())
7457         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7458       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7459       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7460       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7461       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7462         {
7463           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7464           m1ssmSingleAuto.push_back(singleCell);
7465           m1ssmSingle.push_back(singleCell);
7466           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7467         }
7468     }
7469   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7471   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7472   for(std::size_t i=0;i<m1ssm.size();i++)
7473     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7474   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7475   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7476   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7477   return ret0.retn();
7478 }
7479
7480 /*!
7481  * This method returns a newly created DataArrayInt instance.
7482  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7483  */
7484 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7485 {
7486   checkFullyDefined();
7487   const int *conn=_nodal_connec->getConstPointer();
7488   const int *connIndex=_nodal_connec_index->getConstPointer();
7489   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7490   for(const int *w=begin;w!=end;w++)
7491     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7492       ret->pushBackSilent(*w);
7493   return ret.retn();
7494 }
7495
7496 /*!
7497  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7498  * are in [0:getNumberOfCells())
7499  */
7500 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7501 {
7502   checkFullyDefined();
7503   const int *conn=_nodal_connec->getConstPointer();
7504   const int *connI=_nodal_connec_index->getConstPointer();
7505   int nbOfCells=getNumberOfCells();
7506   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7507   int *tmp=new int[nbOfCells];
7508   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7509     {
7510       int j=0;
7511       for(const int *i=connI;i!=connI+nbOfCells;i++)
7512         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7513           tmp[std::distance(connI,i)]=j++;
7514     }
7515   DataArrayInt *ret=DataArrayInt::New();
7516   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7517   ret->copyStringInfoFrom(*da);
7518   int *retPtr=ret->getPointer();
7519   const int *daPtr=da->getConstPointer();
7520   int nbOfElems=da->getNbOfElems();
7521   for(int k=0;k<nbOfElems;k++)
7522     retPtr[k]=tmp[daPtr[k]];
7523   delete [] tmp;
7524   return ret;
7525 }
7526
7527 /*!
7528  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7529  * This method \b works \b for mesh sorted by type.
7530  * cells whose ids is in 'idsPerGeoType' array.
7531  * This method conserves coords and name of mesh.
7532  */
7533 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7534 {
7535   std::vector<int> code=getDistributionOfTypes();
7536   std::size_t nOfTypesInThis=code.size()/3;
7537   int sz=0,szOfType=0;
7538   for(std::size_t i=0;i<nOfTypesInThis;i++)
7539     {
7540       if(code[3*i]!=type)
7541         sz+=code[3*i+1];
7542       else
7543         szOfType=code[3*i+1];
7544     }
7545   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7546     if(*work<0 || *work>=szOfType)
7547       {
7548         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7549         oss << ". It should be in [0," << szOfType << ") !";
7550         throw INTERP_KERNEL::Exception(oss.str().c_str());
7551       }
7552   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7553   int *idsPtr=idsTokeep->getPointer();
7554   int offset=0;
7555   for(std::size_t i=0;i<nOfTypesInThis;i++)
7556     {
7557       if(code[3*i]!=type)
7558         for(int j=0;j<code[3*i+1];j++)
7559           *idsPtr++=offset+j;
7560       else
7561         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7562       offset+=code[3*i+1];
7563     }
7564   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7565   ret->copyTinyInfoFrom(this);
7566   return ret.retn();
7567 }
7568
7569 /*!
7570  * This method returns a vector of size 'this->getNumberOfCells()'.
7571  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7572  */
7573 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7574 {
7575   int ncell=getNumberOfCells();
7576   std::vector<bool> ret(ncell);
7577   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7578   const int *c=getNodalConnectivity()->getConstPointer();
7579   for(int i=0;i<ncell;i++)
7580     {
7581       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7582       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7583       ret[i]=cm.isQuadratic();
7584     }
7585   return ret;
7586 }
7587
7588 /*!
7589  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7590  */
7591 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7592 {
7593   if(other->getType()!=UNSTRUCTURED)
7594     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7595   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7596   return MergeUMeshes(this,otherC);
7597 }
7598
7599 /*!
7600  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7601  * computed by averaging coordinates of cell nodes, so this method is not a right
7602  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7603  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7604  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7605  *          components. The caller is to delete this array using decrRef() as it is
7606  *          no more needed.
7607  *  \throw If the coordinates array is not set.
7608  *  \throw If the nodal connectivity of cells is not defined.
7609  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7610  */
7611 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7612 {
7613   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7614   int spaceDim=getSpaceDimension();
7615   int nbOfCells=getNumberOfCells();
7616   ret->alloc(nbOfCells,spaceDim);
7617   ret->copyStringInfoFrom(*getCoords());
7618   double *ptToFill=ret->getPointer();
7619   const int *nodal=_nodal_connec->getConstPointer();
7620   const int *nodalI=_nodal_connec_index->getConstPointer();
7621   const double *coor=_coords->getConstPointer();
7622   for(int i=0;i<nbOfCells;i++)
7623     {
7624       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7625       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7626       ptToFill+=spaceDim;
7627     }
7628   return ret.retn();
7629 }
7630
7631 /*!
7632  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7633  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7634  * 
7635  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7636  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7637  * 
7638  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7639  * \throw If \a this is not fully defined (coordinates and connectivity)
7640  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7641  */
7642 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7643 {
7644   checkFullyDefined();
7645   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7646   int spaceDim=getSpaceDimension();
7647   int nbOfCells=getNumberOfCells();
7648   int nbOfNodes=getNumberOfNodes();
7649   ret->alloc(nbOfCells,spaceDim);
7650   double *ptToFill=ret->getPointer();
7651   const int *nodal=_nodal_connec->getConstPointer();
7652   const int *nodalI=_nodal_connec_index->getConstPointer();
7653   const double *coor=_coords->getConstPointer();
7654   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7655     {
7656       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7657       std::fill(ptToFill,ptToFill+spaceDim,0.);
7658       if(type!=INTERP_KERNEL::NORM_POLYHED)
7659         {
7660           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7661             {
7662               if(*conn>=0 && *conn<nbOfNodes)
7663                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7664               else
7665                 {
7666                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7667                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7668                 }
7669             }
7670           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7671           if(nbOfNodesInCell>0)
7672             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7673           else
7674             {
7675               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7676               throw INTERP_KERNEL::Exception(oss.str().c_str());
7677             }
7678         }
7679       else
7680         {
7681           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7682           s.erase(-1);
7683           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7684             {
7685               if(*it>=0 && *it<nbOfNodes)
7686                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7687               else
7688                 {
7689                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7690                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7691                 }
7692             }
7693           if(!s.empty())
7694             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7695           else
7696             {
7697               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7698               throw INTERP_KERNEL::Exception(oss.str().c_str());
7699             }
7700         }
7701     }
7702   return ret.retn();
7703 }
7704
7705 /*!
7706  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7707  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7708  * are specified via an array of cell ids. 
7709  *  \warning Validity of the specified cell ids is not checked! 
7710  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7711  *  \param [in] begin - an array of cell ids of interest.
7712  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7713  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7714  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7715  *          caller is to delete this array using decrRef() as it is no more needed. 
7716  *  \throw If the coordinates array is not set.
7717  *  \throw If the nodal connectivity of cells is not defined.
7718  *
7719  *  \if ENABLE_EXAMPLES
7720  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7721  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7722  *  \endif
7723  */
7724 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7725 {
7726   DataArrayDouble *ret=DataArrayDouble::New();
7727   int spaceDim=getSpaceDimension();
7728   int nbOfTuple=(int)std::distance(begin,end);
7729   ret->alloc(nbOfTuple,spaceDim);
7730   double *ptToFill=ret->getPointer();
7731   double *tmp=new double[spaceDim];
7732   const int *nodal=_nodal_connec->getConstPointer();
7733   const int *nodalI=_nodal_connec_index->getConstPointer();
7734   const double *coor=_coords->getConstPointer();
7735   for(const int *w=begin;w!=end;w++)
7736     {
7737       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7738       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7739       ptToFill+=spaceDim;
7740     }
7741   delete [] tmp;
7742   return ret;
7743 }
7744
7745 /*!
7746  * 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".
7747  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7748  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7749  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7750  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7751  * 
7752  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7753  * \throw If spaceDim!=3 or meshDim!=2.
7754  * \throw If connectivity of \a this is invalid.
7755  * \throw If connectivity of a cell in \a this points to an invalid node.
7756  */
7757 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7758 {
7759   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7760   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7761   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7762     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7763   ret->alloc(nbOfCells,4);
7764   double *retPtr(ret->getPointer());
7765   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7766   const double *coor(_coords->begin());
7767   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7768     {
7769       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7770       if(nodalI[1]-nodalI[0]>=3)
7771         {
7772           for(int j=0;j<3;j++)
7773             {
7774               int nodeId(nodal[nodalI[0]+1+j]);
7775               if(nodeId>=0 && nodeId<nbOfNodes)
7776                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7777               else
7778                 {
7779                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7780                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7781                 }
7782             }
7783         }
7784       else
7785         {
7786           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7787           throw INTERP_KERNEL::Exception(oss.str().c_str());
7788         }
7789       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7790       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7791     }
7792   return ret.retn();
7793 }
7794
7795 /*!
7796  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7797  * 
7798  */
7799 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7800 {
7801   if(!da)
7802     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7803   da->checkAllocated();
7804   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7805   ret->setCoords(da);
7806   int nbOfTuples=da->getNumberOfTuples();
7807   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7809   c->alloc(2*nbOfTuples,1);
7810   cI->alloc(nbOfTuples+1,1);
7811   int *cp=c->getPointer();
7812   int *cip=cI->getPointer();
7813   *cip++=0;
7814   for(int i=0;i<nbOfTuples;i++)
7815     {
7816       *cp++=INTERP_KERNEL::NORM_POINT1;
7817       *cp++=i;
7818       *cip++=2*(i+1);
7819     }
7820   ret->setConnectivity(c,cI,true);
7821   return ret.retn();
7822 }
7823 /*!
7824  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7825  * Cells and nodes of
7826  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7827  *  \param [in] mesh1 - the first mesh.
7828  *  \param [in] mesh2 - the second mesh.
7829  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7830  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7831  *          is no more needed.
7832  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7833  *  \throw If the coordinates array is not set in none of the meshes.
7834  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7835  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7836  */
7837 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7838 {
7839   std::vector<const MEDCouplingUMesh *> tmp(2);
7840   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7841   return MergeUMeshes(tmp);
7842 }
7843
7844 /*!
7845  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7846  * Cells and nodes of
7847  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7848  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7849  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7850  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7851  *          is no more needed.
7852  *  \throw If \a a.size() == 0.
7853  *  \throw If \a a[ *i* ] == NULL.
7854  *  \throw If the coordinates array is not set in none of the meshes.
7855  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7856  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7857  */
7858 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7859 {
7860   std::size_t sz=a.size();
7861   if(sz==0)
7862     return MergeUMeshesLL(a);
7863   for(std::size_t ii=0;ii<sz;ii++)
7864     if(!a[ii])
7865       {
7866         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7867         throw INTERP_KERNEL::Exception(oss.str().c_str());
7868       }
7869   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7870   std::vector< const MEDCouplingUMesh * > aa(sz);
7871   int spaceDim=-3;
7872   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7873     {
7874       const MEDCouplingUMesh *cur=a[i];
7875       const DataArrayDouble *coo=cur->getCoords();
7876       if(coo)
7877         spaceDim=coo->getNumberOfComponents();
7878     }
7879   if(spaceDim==-3)
7880     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7881   for(std::size_t i=0;i<sz;i++)
7882     {
7883       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7884       aa[i]=bb[i];
7885     }
7886   return MergeUMeshesLL(aa);
7887 }
7888
7889 /// @cond INTERNAL
7890
7891 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7892 {
7893   if(a.empty())
7894     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7895   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7896   int meshDim=(*it)->getMeshDimension();
7897   int nbOfCells=(*it)->getNumberOfCells();
7898   int meshLgth=(*it++)->getMeshLength();
7899   for(;it!=a.end();it++)
7900     {
7901       if(meshDim!=(*it)->getMeshDimension())
7902         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7903       nbOfCells+=(*it)->getNumberOfCells();
7904       meshLgth+=(*it)->getMeshLength();
7905     }
7906   std::vector<const MEDCouplingPointSet *> aps(a.size());
7907   std::copy(a.begin(),a.end(),aps.begin());
7908   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7909   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7910   ret->setCoords(pts);
7911   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7912   c->alloc(meshLgth,1);
7913   int *cPtr=c->getPointer();
7914   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7915   cI->alloc(nbOfCells+1,1);
7916   int *cIPtr=cI->getPointer();
7917   *cIPtr++=0;
7918   int offset=0;
7919   int offset2=0;
7920   for(it=a.begin();it!=a.end();it++)
7921     {
7922       int curNbOfCell=(*it)->getNumberOfCells();
7923       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7924       const int *curC=(*it)->_nodal_connec->getConstPointer();
7925       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7926       for(int j=0;j<curNbOfCell;j++)
7927         {
7928           const int *src=curC+curCI[j];
7929           *cPtr++=*src++;
7930           for(;src!=curC+curCI[j+1];src++,cPtr++)
7931             {
7932               if(*src!=-1)
7933                 *cPtr=*src+offset2;
7934               else
7935                 *cPtr=-1;
7936             }
7937         }
7938       offset+=curCI[curNbOfCell];
7939       offset2+=(*it)->getNumberOfNodes();
7940     }
7941   //
7942   ret->setConnectivity(c,cI,true);
7943   return ret.retn();
7944 }
7945
7946 /// @endcond
7947
7948 /*!
7949  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7950  * dimension and sharing the node coordinates array.
7951  * All cells of the first mesh precede all cells of the second mesh
7952  * within the result mesh. 
7953  *  \param [in] mesh1 - the first mesh.
7954  *  \param [in] mesh2 - the second mesh.
7955  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7956  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7957  *          is no more needed.
7958  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7959  *  \throw If the meshes do not share the node coordinates array.
7960  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7961  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7962  */
7963 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7964 {
7965   std::vector<const MEDCouplingUMesh *> tmp(2);
7966   tmp[0]=mesh1; tmp[1]=mesh2;
7967   return MergeUMeshesOnSameCoords(tmp);
7968 }
7969
7970 /*!
7971  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7972  * dimension and sharing the node coordinates array.
7973  * All cells of the *i*-th mesh precede all cells of the
7974  * (*i*+1)-th mesh within the result mesh.
7975  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7976  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7977  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7978  *          is no more needed.
7979  *  \throw If \a a.size() == 0.
7980  *  \throw If \a a[ *i* ] == NULL.
7981  *  \throw If the meshes do not share the node coordinates array.
7982  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7983  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7984  */
7985 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7986 {
7987   if(meshes.empty())
7988     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7989   for(std::size_t ii=0;ii<meshes.size();ii++)
7990     if(!meshes[ii])
7991       {
7992         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7993         throw INTERP_KERNEL::Exception(oss.str().c_str());
7994       }
7995   const DataArrayDouble *coords=meshes.front()->getCoords();
7996   int meshDim=meshes.front()->getMeshDimension();
7997   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7998   int meshLgth=0;
7999   int meshIndexLgth=0;
8000   for(;iter!=meshes.end();iter++)
8001     {
8002       if(coords!=(*iter)->getCoords())
8003         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8004       if(meshDim!=(*iter)->getMeshDimension())
8005         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8006       meshLgth+=(*iter)->getMeshLength();
8007       meshIndexLgth+=(*iter)->getNumberOfCells();
8008     }
8009   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
8010   nodal->alloc(meshLgth,1);
8011   int *nodalPtr=nodal->getPointer();
8012   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
8013   nodalIndex->alloc(meshIndexLgth+1,1);
8014   int *nodalIndexPtr=nodalIndex->getPointer();
8015   int offset=0;
8016   for(iter=meshes.begin();iter!=meshes.end();iter++)
8017     {
8018       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8019       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8020       int nbOfCells=(*iter)->getNumberOfCells();
8021       int meshLgth2=(*iter)->getMeshLength();
8022       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8023       if(iter!=meshes.begin())
8024         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8025       else
8026         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8027       offset+=meshLgth2;
8028     }
8029   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8030   ret->setName("merge");
8031   ret->setMeshDimension(meshDim);
8032   ret->setConnectivity(nodal,nodalIndex,true);
8033   ret->setCoords(coords);
8034   return ret;
8035 }
8036
8037 /*!
8038  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8039  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8040  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8041  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8042  * New" mode are returned for each input mesh.
8043  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8044  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8045  *          valid values [0,1,2], see zipConnectivityTraducer().
8046  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8047  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8048  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8049  *          no more needed.
8050  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8051  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8052  *          is no more needed.
8053  *  \throw If \a meshes.size() == 0.
8054  *  \throw If \a meshes[ *i* ] == NULL.
8055  *  \throw If the meshes do not share the node coordinates array.
8056  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8057  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8058  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8059  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8060  */
8061 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8062 {
8063   //All checks are delegated to MergeUMeshesOnSameCoords
8064   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8065   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8066   corr.resize(meshes.size());
8067   std::size_t nbOfMeshes=meshes.size();
8068   int offset=0;
8069   const int *o2nPtr=o2n->getConstPointer();
8070   for(std::size_t i=0;i<nbOfMeshes;i++)
8071     {
8072       DataArrayInt *tmp=DataArrayInt::New();
8073       int curNbOfCells=meshes[i]->getNumberOfCells();
8074       tmp->alloc(curNbOfCells,1);
8075       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8076       offset+=curNbOfCells;
8077       tmp->setName(meshes[i]->getName());
8078       corr[i]=tmp;
8079     }
8080   return ret.retn();
8081 }
8082
8083 /*!
8084  * Makes all given meshes share the nodal connectivity array. The common connectivity
8085  * array is created by concatenating the connectivity arrays of all given meshes. All
8086  * the given meshes must be of the same space dimension but dimension of cells **can
8087  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8088  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8089  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8090  *  \param [in,out] meshes - a vector of meshes to update.
8091  *  \throw If any of \a meshes is NULL.
8092  *  \throw If the coordinates array is not set in any of \a meshes.
8093  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8094  *  \throw If \a meshes are of different space dimension.
8095  */
8096 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8097 {
8098   std::size_t sz=meshes.size();
8099   if(sz==0 || sz==1)
8100     return;
8101   std::vector< const DataArrayDouble * > coords(meshes.size());
8102   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8103   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8104     {
8105       if((*it))
8106         {
8107           (*it)->checkConnectivityFullyDefined();
8108           const DataArrayDouble *coo=(*it)->getCoords();
8109           if(coo)
8110             *it2=coo;
8111           else
8112             {
8113               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8114               oss << " has no coordinate array defined !";
8115               throw INTERP_KERNEL::Exception(oss.str().c_str());
8116             }
8117         }
8118       else
8119         {
8120           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8121           oss << " is null !";
8122           throw INTERP_KERNEL::Exception(oss.str().c_str());
8123         }
8124     }
8125   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8126   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8127   int offset=(*it)->getNumberOfNodes();
8128   (*it++)->setCoords(res);
8129   for(;it!=meshes.end();it++)
8130     {
8131       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8132       (*it)->setCoords(res);
8133       (*it)->shiftNodeNumbersInConn(offset);
8134       offset+=oldNumberOfNodes;
8135     }
8136 }
8137
8138 /*!
8139  * Merges nodes coincident with a given precision within all given meshes that share
8140  * the nodal connectivity array. The given meshes **can be of different** mesh
8141  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8142  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8143  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8144  *  \param [in,out] meshes - a vector of meshes to update.
8145  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8146  *  \throw If any of \a meshes is NULL.
8147  *  \throw If the \a meshes do not share the same node coordinates array.
8148  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8149  */
8150 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8151 {
8152   if(meshes.empty())
8153     return ;
8154   std::set<const DataArrayDouble *> s;
8155   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8156     {
8157       if(*it)
8158         s.insert((*it)->getCoords());
8159       else
8160         {
8161           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 !";
8162           throw INTERP_KERNEL::Exception(oss.str().c_str());
8163         }
8164     }
8165   if(s.size()!=1)
8166     {
8167       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 !";
8168       throw INTERP_KERNEL::Exception(oss.str().c_str());
8169     }
8170   const DataArrayDouble *coo=*(s.begin());
8171   if(!coo)
8172     return;
8173   //
8174   DataArrayInt *comm,*commI;
8175   coo->findCommonTuples(eps,-1,comm,commI);
8176   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8177   int oldNbOfNodes=coo->getNumberOfTuples();
8178   int newNbOfNodes;
8179   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8180   if(oldNbOfNodes==newNbOfNodes)
8181     return ;
8182   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8183   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8184     {
8185       (*it)->renumberNodesInConn(o2n->getConstPointer());
8186       (*it)->setCoords(newCoords);
8187     } 
8188 }
8189
8190 /*!
8191  * 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.
8192  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8193  * \param isQuad specifies the policy of connectivity.
8194  * @ret in/out parameter in which the result will be append
8195  */
8196 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8197 {
8198   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8199   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8200   ret.push_back(cm.getExtrudedType());
8201   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8202   switch(flatType)
8203   {
8204     case INTERP_KERNEL::NORM_POINT1:
8205       {
8206         ret.push_back(connBg[1]);
8207         ret.push_back(connBg[1]+nbOfNodesPerLev);
8208         break;
8209       }
8210     case INTERP_KERNEL::NORM_SEG2:
8211       {
8212         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8213         ret.insert(ret.end(),conn,conn+4);
8214         break;
8215       }
8216     case INTERP_KERNEL::NORM_SEG3:
8217       {
8218         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8219         ret.insert(ret.end(),conn,conn+8);
8220         break;
8221       }
8222     case INTERP_KERNEL::NORM_QUAD4:
8223       {
8224         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8225         ret.insert(ret.end(),conn,conn+8);
8226         break;
8227       }
8228     case INTERP_KERNEL::NORM_TRI3:
8229       {
8230         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8231         ret.insert(ret.end(),conn,conn+6);
8232         break;
8233       }
8234     case INTERP_KERNEL::NORM_TRI6:
8235       {
8236         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,
8237           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8238         ret.insert(ret.end(),conn,conn+15);
8239         break;
8240       }
8241     case INTERP_KERNEL::NORM_QUAD8:
8242       {
8243         int conn[20]={
8244           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8245           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8246           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8247         };
8248         ret.insert(ret.end(),conn,conn+20);
8249         break;
8250       }
8251     case INTERP_KERNEL::NORM_POLYGON:
8252       {
8253         std::back_insert_iterator< std::vector<int> > ii(ret);
8254         std::copy(connBg+1,connEnd,ii);
8255         *ii++=-1;
8256         std::reverse_iterator<const int *> rConnBg(connEnd);
8257         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8258         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8259         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8260         for(std::size_t i=0;i<nbOfRadFaces;i++)
8261           {
8262             *ii++=-1;
8263             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8264             std::copy(conn,conn+4,ii);
8265           }
8266         break;
8267       }
8268     default:
8269       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8270   }
8271 }
8272
8273 /*!
8274  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8275  */
8276 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8277 {
8278   std::size_t i, ip1;
8279   double v[3]={0.,0.,0.};
8280   std::size_t sz=std::distance(begin,end);
8281   if(isQuadratic)
8282     sz/=2;
8283   for(i=0;i<sz;i++)
8284     {
8285       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];
8286       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8287       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8288     }
8289   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8290
8291   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8292   // SEG3 forming a circle):
8293   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8294     {
8295       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8296       for(std::size_t j=0;j<sz;j++)
8297         {
8298           if (j%2)  // current point i is quadratic, next point i+1 is standard
8299             {
8300               i = sz+j;
8301               ip1 = (j+1)%sz; // ip1 = "i+1"
8302             }
8303           else      // current point i is standard, next point i+1 is quadratic
8304             {
8305               i = j;
8306               ip1 = j+sz;
8307             }
8308           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8309           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8310           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8311         }
8312       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8313     }
8314   return (ret>0.);
8315 }
8316
8317 /*!
8318  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8319  */
8320 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8321 {
8322   std::vector<std::pair<int,int> > edges;
8323   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8324   const int *bgFace=begin;
8325   for(std::size_t i=0;i<nbOfFaces;i++)
8326     {
8327       const int *endFace=std::find(bgFace+1,end,-1);
8328       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8329       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8330         {
8331           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8332           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8333             return false;
8334           edges.push_back(p1);
8335         }
8336       bgFace=endFace+1;
8337     }
8338   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8339 }
8340
8341 /*!
8342  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8343  */
8344 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8345 {
8346   double vec0[3],vec1[3];
8347   std::size_t sz=std::distance(begin,end);
8348   if(sz%2!=0)
8349     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8350   int nbOfNodes=(int)sz/2;
8351   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8352   const double *pt0=coords+3*begin[0];
8353   const double *pt1=coords+3*begin[nbOfNodes];
8354   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8355   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8356 }
8357
8358 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8359 {
8360   std::size_t sz=std::distance(begin,end);
8361   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8362   std::size_t nbOfNodes(sz/2);
8363   std::copy(begin,end,(int *)tmp);
8364   for(std::size_t j=1;j<nbOfNodes;j++)
8365     {
8366       begin[j]=tmp[nbOfNodes-j];
8367       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8368     }
8369 }
8370
8371 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8372 {
8373   std::size_t sz=std::distance(begin,end);
8374   if(sz!=4)
8375     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8376   double vec0[3],vec1[3];
8377   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8378   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]; 
8379   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;
8380 }
8381
8382 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8383 {
8384   std::size_t sz=std::distance(begin,end);
8385   if(sz!=5)
8386     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8387   double vec0[3];
8388   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8389   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8390   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8391 }
8392
8393 /*!
8394  * 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 ) 
8395  * 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
8396  * a 2D space.
8397  *
8398  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8399  * \param [in] coords the coordinates with nb of components exactly equal to 3
8400  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8401  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8402  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8403  */
8404 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8405 {
8406   int nbFaces=std::count(begin+1,end,-1)+1;
8407   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8408   double *vPtr=v->getPointer();
8409   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8410   double *pPtr=p->getPointer();
8411   const int *stFaceConn=begin+1;
8412   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8413     {
8414       const int *endFaceConn=std::find(stFaceConn,end,-1);
8415       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8416       stFaceConn=endFaceConn+1;
8417     }
8418   pPtr=p->getPointer(); vPtr=v->getPointer();
8419   DataArrayInt *comm1=0,*commI1=0;
8420   v->findCommonTuples(eps,-1,comm1,commI1);
8421   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8422   const int *comm1Ptr=comm1->getConstPointer();
8423   const int *commI1Ptr=commI1->getConstPointer();
8424   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8425   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8426   //
8427   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8428   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8429   mm->finishInsertingCells();
8430   //
8431   for(int i=0;i<nbOfGrps1;i++)
8432     {
8433       int vecId=comm1Ptr[commI1Ptr[i]];
8434       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8435       DataArrayInt *comm2=0,*commI2=0;
8436       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8437       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8438       const int *comm2Ptr=comm2->getConstPointer();
8439       const int *commI2Ptr=commI2->getConstPointer();
8440       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8441       for(int j=0;j<nbOfGrps2;j++)
8442         {
8443           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8444             {
8445               res->insertAtTheEnd(begin,end);
8446               res->pushBackSilent(-1);
8447             }
8448           else
8449             {
8450               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8451               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8452               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8453               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8454               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8455               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8456               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8457               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8458               const int *idsNodePtr=idsNode->getConstPointer();
8459               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];
8460               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8461               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8462               if(std::abs(norm)>eps)
8463                 {
8464                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8465                   mm3->rotate(center,vec,angle);
8466                 }
8467               mm3->changeSpaceDimension(2);
8468               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8469               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8470               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8471               int nbOfCells=mm4->getNumberOfCells();
8472               for(int k=0;k<nbOfCells;k++)
8473                 {
8474                   int l=0;
8475                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8476                     res->pushBackSilent(idsNodePtr[*work]);
8477                   res->pushBackSilent(-1);
8478                 }
8479             }
8480         }
8481     }
8482   res->popBackSilent();
8483 }
8484
8485 /*!
8486  * 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
8487  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8488  * 
8489  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8490  * \param [in] coords coordinates expected to have 3 components.
8491  * \param [in] begin start of the nodal connectivity of the face.
8492  * \param [in] end end of the nodal connectivity (excluded) of the face.
8493  * \param [out] v the normalized vector of size 3
8494  * \param [out] p the pos of plane
8495  */
8496 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8497 {
8498   std::size_t nbPoints=std::distance(begin,end);
8499   if(nbPoints<3)
8500     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8501   double vec[3]={0.,0.,0.};
8502   std::size_t j=0;
8503   bool refFound=false;
8504   for(;j<nbPoints-1 && !refFound;j++)
8505     {
8506       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8507       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8508       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8509       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8510       if(norm>eps)
8511         {
8512           refFound=true;
8513           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8514         }
8515     }
8516   for(std::size_t i=j;i<nbPoints-1;i++)
8517     {
8518       double curVec[3];
8519       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8520       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8521       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8522       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8523       if(norm<eps)
8524         continue;
8525       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8526       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];
8527       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8528       if(norm>eps)
8529         {
8530           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8531           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8532           return ;
8533         }
8534     }
8535   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8536 }
8537
8538 /*!
8539  * This method tries to obtain a well oriented polyhedron.
8540  * If the algorithm fails, an exception will be thrown.
8541  */
8542 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8543 {
8544   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8545   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8546   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8547   isPerm[0]=true;
8548   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8549   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8550   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8551   //
8552   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8553     {
8554       bgFace=begin;
8555       std::size_t smthChanged=0;
8556       for(std::size_t i=0;i<nbOfFaces;i++)
8557         {
8558           endFace=std::find(bgFace+1,end,-1);
8559           nbOfEdgesInFace=std::distance(bgFace,endFace);
8560           if(!isPerm[i])
8561             {
8562               bool b;
8563               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8564                 {
8565                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8566                   std::pair<int,int> p2(p1.second,p1.first);
8567                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8568                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8569                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8570                 }
8571               if(isPerm[i])
8572                 { 
8573                   if(!b)
8574                     std::reverse(bgFace+1,endFace);
8575                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8576                     {
8577                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8578                       std::pair<int,int> p2(p1.second,p1.first);
8579                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8580                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8581                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8582                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8583                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8584                       if(it!=edgesOK.end())
8585                         {
8586                           edgesOK.erase(it);
8587                           edgesFinished.push_back(p1);
8588                         }
8589                       else
8590                         edgesOK.push_back(p1);
8591                     }
8592                 }
8593             }
8594           bgFace=endFace+1;
8595         }
8596       if(smthChanged==0)
8597         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8598     }
8599   if(!edgesOK.empty())
8600     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8601   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8602     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8603       bgFace=begin;
8604       for(std::size_t i=0;i<nbOfFaces;i++)
8605         {
8606           endFace=std::find(bgFace+1,end,-1);
8607           std::reverse(bgFace+1,endFace);
8608           bgFace=endFace+1;
8609         }
8610     }
8611 }
8612
8613 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8614 {
8615   int nbOfNodesExpected(skin->getNumberOfNodes());
8616   const int *n2oPtr(n2o->getConstPointer());
8617   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8618   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8619   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8620   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8621   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8622   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8623   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8624   if(nbOfNodesExpected<1)
8625     return ret.retn();
8626   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8627   *work++=n2oPtr[prevNode];
8628   for(int i=1;i<nbOfNodesExpected;i++)
8629     {
8630       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8631         {
8632           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8633           conn.erase(prevNode);
8634           if(conn.size()==1)
8635             {
8636               int curNode(*(conn.begin()));
8637               *work++=n2oPtr[curNode];
8638               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8639               shar.erase(prevCell);
8640               if(shar.size()==1)
8641                 {
8642                   prevCell=*(shar.begin());
8643                   prevNode=curNode;
8644                 }
8645               else
8646                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8647             }
8648           else
8649             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8650         }
8651       else
8652         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8653     }
8654   return ret.retn();
8655 }
8656
8657 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8658 {
8659   int nbOfNodesExpected(skin->getNumberOfNodes());
8660   int nbOfTurn(nbOfNodesExpected/2);
8661   const int *n2oPtr(n2o->getConstPointer());
8662   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8663   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8664   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8665   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8666   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8667   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8668   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8669   if(nbOfNodesExpected<1)
8670     return ret.retn();
8671   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8672   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8673   for(int i=1;i<nbOfTurn;i++)
8674     {
8675       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8676         {
8677           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8678           conn.erase(prevNode);
8679           if(conn.size()==1)
8680             {
8681               int curNode(*(conn.begin()));
8682               *work=n2oPtr[curNode];
8683               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8684               shar.erase(prevCell);
8685               if(shar.size()==1)
8686                 {
8687                   int curCell(*(shar.begin()));
8688                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8689                   prevCell=curCell;
8690                   prevNode=curNode;
8691                   work++;
8692                 }
8693               else
8694                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8695             }
8696           else
8697             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8698         }
8699       else
8700         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8701     }
8702   return ret.retn();
8703 }
8704
8705 /*!
8706  * This method makes the assumption spacedimension == meshdimension == 2.
8707  * This method works only for linear cells.
8708  * 
8709  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8710  */
8711 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8712 {
8713   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8714     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8715   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8716   int oldNbOfNodes(skin->getNumberOfNodes());
8717   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8718   int nbOfNodesExpected(skin->getNumberOfNodes());
8719   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8720   int nbCells(skin->getNumberOfCells());
8721   if(nbCells==nbOfNodesExpected)
8722     return buildUnionOf2DMeshLinear(skin,n2o);
8723   else if(2*nbCells==nbOfNodesExpected)
8724     return buildUnionOf2DMeshQuadratic(skin,n2o);
8725   else
8726     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8727 }
8728
8729 /*!
8730  * This method makes the assumption spacedimension == meshdimension == 3.
8731  * This method works only for linear cells.
8732  * 
8733  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8734  */
8735 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8736 {
8737   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8738     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8739   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8740   const int *conn=m->getNodalConnectivity()->getConstPointer();
8741   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8742   int nbOfCells=m->getNumberOfCells();
8743   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8744   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8745   if(nbOfCells<1)
8746     return ret.retn();
8747   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8748   for(int i=1;i<nbOfCells;i++)
8749     {
8750       *work++=-1;
8751       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8752     }
8753   return ret.retn();
8754 }
8755
8756 /*!
8757  * \brief Creates a graph of cell neighbors
8758  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8759  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8760  *  For example
8761  *  - index:  0 3 5 6 6
8762  *  - value:  1 2 3 2 3 3
8763  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8764  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8765  */
8766 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8767 {
8768   checkConnectivityFullyDefined();
8769
8770   int meshDim = this->getMeshDimension();
8771   ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8772   ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8773   this->getReverseNodalConnectivity(revConn,indexr);
8774   const int* indexr_ptr=indexr->getConstPointer();
8775   const int* revConn_ptr=revConn->getConstPointer();
8776
8777   const ParaMEDMEM::DataArrayInt* index;
8778   const ParaMEDMEM::DataArrayInt* conn;
8779   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8780   index=this->getNodalConnectivityIndex();
8781   int nbCells=this->getNumberOfCells();
8782   const int* index_ptr=index->getConstPointer();
8783   const int* conn_ptr=conn->getConstPointer();
8784
8785   //creating graph arcs (cell to cell relations)
8786   //arcs are stored in terms of (index,value) notation
8787   // 0 3 5 6 6
8788   // 1 2 3 2 3 3
8789   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8790   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8791
8792   //warning here one node have less than or equal effective number of cell with it
8793   //but cell could have more than effective nodes
8794   //because other equals nodes in other domain (with other global inode)
8795   std::vector <int> cell2cell_index(nbCells+1,0);
8796   std::vector <int> cell2cell;
8797   cell2cell.reserve(3*nbCells);
8798
8799   for (int icell=0; icell<nbCells;icell++)
8800     {
8801       std::map<int,int > counter;
8802       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8803         {
8804           int inode=conn_ptr[iconn];
8805           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8806             {
8807               int icell2=revConn_ptr[iconnr];
8808               std::map<int,int>::iterator iter=counter.find(icell2);
8809               if (iter!=counter.end()) (iter->second)++;
8810               else counter.insert(std::make_pair(icell2,1));
8811             }
8812         }
8813       for (std::map<int,int>::const_iterator iter=counter.begin();
8814            iter!=counter.end(); iter++)
8815         if (iter->second >= meshDim)
8816           {
8817             cell2cell_index[icell+1]++;
8818             cell2cell.push_back(iter->first);
8819           }
8820     }
8821   indexr->decrRef();
8822   revConn->decrRef();
8823   cell2cell_index[0]=0;
8824   for (int icell=0; icell<nbCells;icell++)
8825     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8826
8827   //filling up index and value to create skylinearray structure
8828   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8829   return array;
8830 }
8831
8832 /*!
8833  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8834  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8835  */
8836 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8837 {
8838   double *w=zipFrmt;
8839   if(spaceDim==3)
8840     for(int i=0;i<nbOfNodesInCell;i++)
8841       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8842   else if(spaceDim==2)
8843     {
8844       for(int i=0;i<nbOfNodesInCell;i++)
8845         {
8846           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8847           *w++=0.;
8848         }
8849     }
8850   else
8851     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8852 }
8853
8854 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8855 {
8856   int nbOfCells=getNumberOfCells();
8857   if(nbOfCells<=0)
8858     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8859   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};
8860   ofs << "  <" << getVTKDataSetType() << ">\n";
8861   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8862   ofs << "      <PointData>\n" << pointData << std::endl;
8863   ofs << "      </PointData>\n";
8864   ofs << "      <CellData>\n" << cellData << std::endl;
8865   ofs << "      </CellData>\n";
8866   ofs << "      <Points>\n";
8867   if(getSpaceDimension()==3)
8868     _coords->writeVTK(ofs,8,"Points",byteData);
8869   else
8870     {
8871       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8872       coo->writeVTK(ofs,8,"Points",byteData);
8873     }
8874   ofs << "      </Points>\n";
8875   ofs << "      <Cells>\n";
8876   const int *cPtr=_nodal_connec->getConstPointer();
8877   const int *cIPtr=_nodal_connec_index->getConstPointer();
8878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8879   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8881   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8882   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8883   int szFaceOffsets=0,szConn=0;
8884   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8885     {
8886       *w2=cPtr[cIPtr[i]];
8887       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8888         {
8889           *w1=-1;
8890           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8891           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8892         }
8893       else
8894         {
8895           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8896           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8897           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8898           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8899           w4=std::copy(c.begin(),c.end(),w4);
8900         }
8901     }
8902   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8903   types->writeVTK(ofs,8,"UInt8","types",byteData);
8904   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8905   if(szFaceOffsets!=0)
8906     {//presence of Polyhedra
8907       connectivity->reAlloc(szConn);
8908       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8909       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8910       w1=faces->getPointer();
8911       for(int i=0;i<nbOfCells;i++)
8912         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8913           {
8914             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8915             *w1++=nbFaces;
8916             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8917             for(int j=0;j<nbFaces;j++)
8918               {
8919                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8920                 *w1++=(int)std::distance(w6,w5);
8921                 w1=std::copy(w6,w5,w1);
8922                 w6=w5+1;
8923               }
8924           }
8925       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8926     }
8927   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8928   ofs << "      </Cells>\n";
8929   ofs << "    </Piece>\n";
8930   ofs << "  </" << getVTKDataSetType() << ">\n";
8931 }
8932
8933 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8934 {
8935   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8936   if(_mesh_dim==-2)
8937     { stream << " Not set !"; return ; }
8938   stream << " Mesh dimension : " << _mesh_dim << ".";
8939   if(_mesh_dim==-1)
8940     return ;
8941   if(!_coords)
8942     { stream << " No coordinates set !"; return ; }
8943   if(!_coords->isAllocated())
8944     { stream << " Coordinates set but not allocated !"; return ; }
8945   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8946   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8947   if(!_nodal_connec_index)
8948     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8949   if(!_nodal_connec_index->isAllocated())
8950     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8951   int lgth=_nodal_connec_index->getNumberOfTuples();
8952   int cpt=_nodal_connec_index->getNumberOfComponents();
8953   if(cpt!=1 || lgth<1)
8954     return ;
8955   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8956 }
8957
8958 std::string MEDCouplingUMesh::getVTKDataSetType() const
8959 {
8960   return std::string("UnstructuredGrid");
8961 }
8962
8963 std::string MEDCouplingUMesh::getVTKFileExtension() const
8964 {
8965   return std::string("vtu");
8966 }
8967
8968 /*!
8969  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8970  * returns a result mesh constituted by polygons.
8971  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8972  * all nodes from m2.
8973  * The meshes should be in 2D space. In
8974  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8975  * meshes.
8976  *  \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
8977  *                      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)
8978  *  \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
8979  *                      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)
8980  *  \param [in] eps - precision used to detect coincident mesh entities.
8981  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8982  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8983  *         this array using decrRef() as it is no more needed.
8984  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8985  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8986  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8987  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8988  *         it is no more needed.  
8989  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8990  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8991  *         is no more needed.  
8992  *  \throw If the coordinates array is not set in any of the meshes.
8993  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8994  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8995  *
8996  *  \sa conformize2D, mergeNodes
8997  */
8998 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8999                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9000 {
9001   if(!m1 || !m2)
9002     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9003   m1->checkFullyDefined();
9004   m2->checkFullyDefined();
9005   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9006     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
9007
9008   // Step 1: compute all edge intersections (new nodes)
9009   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9010   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9011   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9012   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9013   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9014                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9015                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9016   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9017   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9018   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9019
9020   // Step 2: re-order newly created nodes according to the ordering found in m2
9021   std::vector< std::vector<int> > intersectEdge2;
9022   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9023   subDiv2.clear(); dd5=0; dd6=0;
9024
9025   // Step 3:
9026   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9027   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9028   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9029                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9030
9031   // Step 4: Prepare final result:
9032   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9033   addCooDa->alloc((int)(addCoo.size())/2,2);
9034   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9035   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9036   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9037   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9038   std::vector<const DataArrayDouble *> coordss(4);
9039   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9040   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9041   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9042   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9043   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9044   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9045   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9046   ret->setConnectivity(conn,connI,true);
9047   ret->setCoords(coo);
9048   cellNb1=c1.retn(); cellNb2=c2.retn();
9049   return ret.retn();
9050 }
9051
9052 /// @cond INTERNAL
9053
9054 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9055 {
9056   if(candidates.empty())
9057     return false;
9058   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9059     {
9060       const std::vector<int>& pool(intersectEdge1[*it]);
9061       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9062       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9063         {
9064           retVal=*it+1;
9065           return true;
9066         }
9067       tmp[0]=stop; tmp[1]=start;
9068       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9069         {
9070           retVal=-*it-1;
9071           return true;
9072         }
9073     }
9074   return false;
9075 }
9076
9077 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,
9078                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9079 {
9080   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9081   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9082   int nCells(mesh1D->getNumberOfCells());
9083   if(nCells!=(int)intersectEdge2.size())
9084     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9085   const DataArrayDouble *coo2(mesh1D->getCoords());
9086   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9087   const double *coo2Ptr(coo2->begin());
9088   int offset1(coords1->getNumberOfTuples());
9089   int offset2(offset1+coo2->getNumberOfTuples());
9090   int offset3(offset2+addCoo.size()/2);
9091   std::vector<double> addCooQuad;
9092   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9093   int tmp[4],cicnt(0),kk(0);
9094   for(int i=0;i<nCells;i++)
9095     {
9096       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9097       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9098       const std::vector<int>& subEdges(intersectEdge2[i]);
9099       int nbSubEdge(subEdges.size()/2);
9100       for(int j=0;j<nbSubEdge;j++,kk++)
9101         {
9102           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));
9103           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9104           INTERP_KERNEL::Edge *e2Ptr(e2);
9105           std::map<int,int>::const_iterator itm;
9106           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9107             {
9108               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9109               itm=mergedNodes.find(subEdges[2*j]);
9110               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9111               itm=mergedNodes.find(subEdges[2*j+1]);
9112               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9113               tmp[3]=offset3+(int)addCooQuad.size()/2;
9114               double tmp2[2];
9115               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9116               cicnt+=4;
9117               cOut->insertAtTheEnd(tmp,tmp+4);
9118               ciOut->pushBackSilent(cicnt);
9119             }
9120           else
9121             {
9122               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9123               itm=mergedNodes.find(subEdges[2*j]);
9124               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9125               itm=mergedNodes.find(subEdges[2*j+1]);
9126               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9127               cicnt+=3;
9128               cOut->insertAtTheEnd(tmp,tmp+3);
9129               ciOut->pushBackSilent(cicnt);
9130             }
9131           int tmp00;
9132           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9133             {
9134               idsInRetColinear->pushBackSilent(kk);
9135               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9136             }
9137         }
9138       e->decrRef();
9139     }
9140   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9141   ret->setConnectivity(cOut,ciOut,true);
9142   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9143   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9144   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9145   std::vector<const DataArrayDouble *> coordss(4);
9146   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9147   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9148   ret->setCoords(arr);
9149   return ret.retn();
9150 }
9151
9152 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9153 {
9154   std::vector<int> allEdges;
9155   for(const int *it2(descBg);it2!=descEnd;it2++)
9156     {
9157       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9158       if(*it2>0)
9159         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9160       else
9161         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9162     }
9163   std::size_t nb(allEdges.size());
9164   if(nb%2!=0)
9165     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9166   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9167   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9168   ret->setCoords(coords);
9169   ret->allocateCells(1);
9170   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9171   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9172     connOut[kk]=allEdges[2*kk];
9173   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9174   return ret.retn();
9175 }
9176
9177 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9178 {
9179   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9180   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9181   std::size_t ii(0);
9182   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9183   if(sz!=std::distance(descBg,descEnd))
9184     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9185   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9186   std::vector<int> allEdges,centers;
9187   const double *coordsPtr(coords->begin());
9188   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9189   int offset(coords->getNumberOfTuples());
9190   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9191     {
9192       INTERP_KERNEL::NormalizedCellType typeOfSon;
9193       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9194       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9195       if(*it2>0)
9196         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9197       else
9198         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9199       if(edge1.size()==2)
9200         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9201       else
9202         {//the current edge has been subsplit -> create corresponding centers.
9203           std::size_t nbOfCentersToAppend(edge1.size()/2);
9204           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9205           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9206           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9207           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9208             {
9209               double tmpp[2];
9210               const double *aa(coordsPtr+2*(*it3++));
9211               const double *bb(coordsPtr+2*(*it3++));
9212               ee->getMiddleOfPoints(aa,bb,tmpp);
9213               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9214               centers.push_back(offset+k);
9215             }
9216         }
9217     }
9218   std::size_t nb(allEdges.size());
9219   if(nb%2!=0)
9220     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9221   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9222   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9223   if(addCoo->empty())
9224     ret->setCoords(coords);
9225   else
9226     {
9227       addCoo->rearrange(2);
9228       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9229       ret->setCoords(addCoo);
9230     }
9231   ret->allocateCells(1);
9232   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9233   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9234     connOut[kk]=allEdges[2*kk];
9235   connOut.insert(connOut.end(),centers.begin(),centers.end());
9236   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9237   return ret.retn();
9238 }
9239
9240 /*!
9241  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9242  * of those edges.
9243  *
9244  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9245  */
9246 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9247 {
9248   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9249   if(!cm.isQuadratic())
9250     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9251   else
9252     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9253 }
9254
9255 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9256 {
9257   bool isQuad(false);
9258   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9259     {
9260       const INTERP_KERNEL::Edge *ee(*it);
9261       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9262         isQuad=true;
9263     }
9264   if(!isQuad)
9265     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9266   else
9267     {
9268       const double *coo(mesh2D->getCoords()->begin());
9269       std::size_t sz(conn.size());
9270       std::vector<double> addCoo;
9271       std::vector<int> conn2(conn);
9272       int offset(mesh2D->getNumberOfNodes());
9273       for(std::size_t i=0;i<sz;i++)
9274         {
9275           double tmp[2];
9276           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9277           addCoo.insert(addCoo.end(),tmp,tmp+2);
9278           conn2.push_back(offset+(int)i);
9279         }
9280       mesh2D->getCoords()->rearrange(1);
9281       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9282       mesh2D->getCoords()->rearrange(2);
9283       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9284     }
9285 }
9286
9287 /*!
9288  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9289  *
9290  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9291  * a set of edges defined in \a splitMesh1D.
9292  */
9293 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9294                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9295 {
9296   std::size_t nb(edge1Bis.size()/2);
9297   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9298   int iEnd(splitMesh1D->getNumberOfCells());
9299   if(iEnd==0)
9300     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9301   std::size_t ii,jj;
9302   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9303   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9304   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9305   //
9306   if(jj==nb)
9307     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9308       out0.resize(1); out1.resize(1);
9309       std::vector<int>& connOut(out0[0]);
9310       connOut.resize(nbOfEdgesOf2DCellSplit);
9311       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9312       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9313       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9314         {
9315           connOut[kk]=edge1Bis[2*kk];
9316           edgesPtr[kk]=edge1BisPtr[2*kk];
9317         }
9318     }
9319   else
9320     {
9321       // [i,iEnd[ contains the
9322       out0.resize(2); out1.resize(2);
9323       std::vector<int>& connOutLeft(out0[0]);
9324       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9325       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9326       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9327       for(std::size_t k=ii;k<jj+1;k++)
9328         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9329       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9330       for(int ik=0;ik<iEnd;ik++)
9331         {
9332           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9333           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9334           ees[ik]=ee;
9335         }
9336       for(int ik=iEnd-1;ik>=0;ik--)
9337         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9338       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9339         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9340       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9341       for(int ik=0;ik<iEnd;ik++)
9342         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9343       eright.insert(eright.end(),ees.begin(),ees.end());
9344     }
9345 }
9346
9347 /// @endcond
9348
9349 /// @cond INTERNAL
9350
9351 struct CellInfo
9352 {
9353 public:
9354   CellInfo() { }
9355   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9356 public:
9357   std::vector<int> _edges;
9358   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9359 };
9360
9361 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9362 {
9363   std::size_t nbe(edges.size());
9364   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9365   for(std::size_t i=0;i<nbe;i++)
9366     {
9367       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9368       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9369     }
9370   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9371   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9372   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9373 }
9374
9375 class EdgeInfo
9376 {
9377 public:
9378   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9379   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9380   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9381   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9382   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9383 private:
9384   int _istart;
9385   int _iend;
9386   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9387   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9388   int _left;
9389   int _right;
9390 };
9391
9392 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9393 {
9394   const MEDCouplingUMesh *mesh(_mesh);
9395   if(mesh)
9396     return ;
9397   if(_right<pos)
9398     return ;
9399   if(_left>pos)
9400     { _left++; _right++; return ; }
9401   if(_right==pos)
9402     {
9403       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9404       if((isLeft && isRight) || (!isLeft && !isRight))
9405         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9406       if(isLeft)
9407         return ;
9408       if(isRight)
9409         {
9410           _right++;
9411           return ;
9412         }
9413     }
9414   if(_left==pos)
9415     {
9416       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9417       if((isLeft && isRight) || (!isLeft && !isRight))
9418         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9419       if(isLeft)
9420         {
9421           _right++;
9422           return ;
9423         }
9424       if(isRight)
9425         {
9426           _left++;
9427           _right++;
9428           return ;
9429         }
9430     }
9431 }
9432
9433 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9434 {
9435   const MEDCouplingUMesh *mesh(_mesh);
9436   if(!mesh)
9437     {
9438       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9439     }
9440   else
9441     {// not fully splitting cell case
9442       if(mesh2D->getNumberOfCells()==1)
9443         {//little optimization. 1 cell no need to find in which cell mesh is !
9444           neighbors[0]=offset; neighbors[1]=offset;
9445           return;
9446         }
9447       else
9448         {
9449           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9450           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9451           if(cellId==-1)
9452             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9453           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9454         }
9455     }
9456 }
9457
9458 class VectorOfCellInfo
9459 {
9460 public:
9461   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9462   std::size_t size() const { return _pool.size(); }
9463   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9464   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);
9465   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9466   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9467   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9468   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9469 private:
9470   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9471   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9472   const CellInfo& get(int pos) const;
9473   CellInfo& get(int pos);
9474 private:
9475   std::vector<CellInfo> _pool;
9476   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9477   std::vector<EdgeInfo> _edge_info;
9478 };
9479
9480 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9481 {
9482   _pool[0]._edges=edges;
9483   _pool[0]._edges_ptr=edgesPtr;
9484 }
9485
9486 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9487 {
9488   if(_pool.empty())
9489     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9490   if(_pool.size()==1)
9491     return 0;
9492   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9493   if(!zeMesh)
9494     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9495   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9496   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9497 }
9498
9499 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)
9500 {
9501   get(pos);//to check pos
9502   bool isFast(pos==0 && _pool.size()==1);
9503   std::size_t sz(edges.size());
9504   // dealing with edges
9505   if(sz==1)
9506     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9507   else
9508     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9509   //
9510   std::vector<CellInfo> pool(_pool.size()-1+sz);
9511   for(int i=0;i<pos;i++)
9512     pool[i]=_pool[i];
9513   for(std::size_t j=0;j<sz;j++)
9514     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9515   for(int i=pos+1;i<(int)_pool.size();i++)
9516     pool[i+sz-1]=_pool[i];
9517   _pool=pool;
9518   //
9519   if(sz==2)
9520     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9521   //
9522   if(isFast)
9523     {
9524       _ze_mesh=mesh;
9525       return ;
9526     }
9527   //
9528   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9529   if(pos>0)
9530     {
9531       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9532       ms.push_back(elt);
9533     }
9534   ms.push_back(mesh);
9535   if(pos<_ze_mesh->getNumberOfCells()-1)
9536   {
9537     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9538     ms.push_back(elt);
9539   }
9540   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9541   for(std::size_t j=0;j<ms2.size();j++)
9542     ms2[j]=ms[j];
9543   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9544 }
9545
9546 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9547 {
9548   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9549 }
9550
9551 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9552 {
9553   if(pos<0)
9554     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9555   int ret(0);
9556   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9557     {
9558       if((*it).isInMyRange(pos))
9559         return ret;
9560     }
9561   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9562 }
9563
9564 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9565 {
9566   get(pos);//to check;
9567   if(_edge_info.empty())
9568     return ;
9569   std::size_t sz(_edge_info.size()-1);
9570   for(std::size_t i=0;i<sz;i++)
9571     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9572 }
9573
9574 const CellInfo& VectorOfCellInfo::get(int pos) const
9575 {
9576   if(pos<0 || pos>=(int)_pool.size())
9577     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9578   return _pool[pos];
9579 }
9580
9581 CellInfo& VectorOfCellInfo::get(int pos)
9582 {
9583   if(pos<0 || pos>=(int)_pool.size())
9584     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9585   return _pool[pos];
9586 }
9587
9588 /*!
9589  * Given :
9590  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9591  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9592  *
9593  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9594  *
9595  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9596  *
9597  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9598  */
9599 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9600                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9601 {
9602   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9603   if(nbCellsInSplitMesh1D==0)
9604     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9605   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9606   std::size_t nb(allEdges.size()),jj;
9607   if(nb%2!=0)
9608     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9609   std::vector<int> edge1Bis(nb*2);
9610   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9611   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9612   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9613   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9614   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9615   //
9616   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9617   int *idsLeftRightPtr(idsLeftRight->getPointer());
9618   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9619   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9620     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9621       int iEnd(iStart);
9622       for(;iEnd<nbCellsInSplitMesh1D;)
9623         {
9624           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9625           if(jj!=nb)
9626             break;
9627           else
9628             iEnd++;
9629         }
9630       if(iEnd<nbCellsInSplitMesh1D)
9631         iEnd++;
9632       //
9633       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9634       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9635       //
9636       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9637       retTmp->setCoords(splitMesh1D->getCoords());
9638       retTmp->allocateCells();
9639
9640       std::vector< std::vector<int> > out0;
9641       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9642
9643       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9644       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9645         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9646       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9647       //
9648       iStart=iEnd;
9649     }
9650   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9651     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9652   return pool.getZeMesh().retn();
9653 }
9654
9655 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9656                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9657                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9658 {
9659   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9660   //
9661   std::vector<int> allEdges;
9662   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9663   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9664     {
9665       int edgeId(std::abs(*it)-1);
9666       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9667       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9668       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9669       if(*it>0)
9670         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9671       else
9672         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9673       std::size_t sz(edge1.size());
9674       for(std::size_t cnt=0;cnt<sz;cnt++)
9675         allEdgesPtr.push_back(ee);
9676     }
9677   //
9678   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9679 }
9680
9681 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9682 {
9683   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9684     {//easy case comparison not
9685       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9686     }
9687   else if(typ1.isQuadratic() && typ2.isQuadratic())
9688     {
9689       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9690       if(!status0)
9691         return false;
9692       if(conn1[2]==conn2[2])
9693         return true;
9694       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9695       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9696       return dist<eps;
9697     }
9698   else
9699     {//only one is quadratic
9700       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9701       if(!status0)
9702         return false;
9703       const double *a(0),*bb(0),*be(0);
9704       if(typ1.isQuadratic())
9705         {
9706           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9707         }
9708       else
9709         {
9710           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9711         }
9712       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9713       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9714       return dist<eps;
9715     }
9716 }
9717
9718 /*!
9719  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9720  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9721  *
9722  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9723  */
9724 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9725 {
9726   if(candidatesIn2DEnd==candidatesIn2DBg)
9727     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9728   const double *coo(mesh2DSplit->getCoords()->begin());
9729   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9730     return *candidatesIn2DBg;
9731   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9732   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9733   if(cellIdInMesh1DSplitRelative<0)
9734     cur1D->changeOrientationOfCells();
9735   const int *c1D(cur1D->getNodalConnectivity()->begin());
9736   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9737   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9738     {
9739       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9740       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9741       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9742       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9743       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9744       for(unsigned it2=0;it2<sz;it2++)
9745         {
9746           INTERP_KERNEL::NormalizedCellType typeOfSon;
9747           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9748           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9749           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9750             return *it;
9751         }
9752     }
9753   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9754 }
9755
9756 /// @endcond
9757
9758 /*!
9759  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9760  * 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
9761  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9762  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9763  *
9764  * \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
9765  *                      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)
9766  * \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
9767  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9768  * \param [in] eps - precision used to perform intersections and localization operations.
9769  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9770  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9771  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9772  *                               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.
9773  * \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
9774  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9775  *                               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.
9776  *
9777  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9778  */
9779 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9780 {
9781   if(!mesh2D || !mesh1D)
9782     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9783   mesh2D->checkFullyDefined();
9784   mesh1D->checkFullyDefined();
9785   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9786   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9787     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9788   // Step 1: compute all edge intersections (new nodes)
9789   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9790   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9791   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9792   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9793   //
9794   // Build desc connectivity
9795   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9796   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9797   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9798   std::map<int,int> mergedNodes;
9799   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9800   // use mergeNodes to fix intersectEdge1
9801   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9802     {
9803       std::size_t n((*it0).size()/2);
9804       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9805       std::map<int,int>::const_iterator it1;
9806       it1=mergedNodes.find(eltStart);
9807       if(it1!=mergedNodes.end())
9808         (*it0)[0]=(*it1).second;
9809       it1=mergedNodes.find(eltEnd);
9810       if(it1!=mergedNodes.end())
9811         (*it0)[2*n-1]=(*it1).second;
9812     }
9813   //
9814   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9815   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9816   // Step 2: re-order newly created nodes according to the ordering found in m2
9817   std::vector< std::vector<int> > intersectEdge2;
9818   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9819   subDiv2.clear();
9820   // Step 3: compute splitMesh1D
9821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9823   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9824       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9825   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9826   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9827   // deal with cells in mesh2D that are not cut but only some of their edges are
9828   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9829   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9830   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9831   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
9832   if(!idsInDesc2DToBeRefined->empty())
9833     {
9834       DataArrayInt *out0(0),*outi0(0);
9835       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9836       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9837       out0s=out0;
9838       out0s=out0s->buildUnique();
9839       out0s->sort(true);
9840     }
9841   //
9842   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9843   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9844   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9845   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9846   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9847   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9848   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9849     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9850   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9851   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9852   if((DataArrayInt *)out0s)
9853     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9854   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9855   // OK all is ready to insert in ret2 mesh
9856   if(!untouchedCells->empty())
9857     {// the most easy part, cells in mesh2D not impacted at all
9858       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9859       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9860       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9861     }
9862   if((DataArrayInt *)out0s)
9863     {// here dealing with cells in out0s but not in cellsToBeModified
9864       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9865       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9866       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9867         {
9868           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9869           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9870         }
9871       int offset(ret2->getNumberOfTuples());
9872       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9873       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9874       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9875       int kk(0),*ret3ptr(partOfRet3->getPointer());
9876       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9877         {
9878           int faceId(std::abs(*it)-1);
9879           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9880             {
9881               int tmp(fewModifiedCells->locateValue(*it2));
9882               if(tmp!=-1)
9883                 {
9884                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9885                     ret3ptr[2*kk]=tmp+offset;
9886                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9887                     ret3ptr[2*kk+1]=tmp+offset;
9888                 }
9889               else
9890                 {//the current edge is shared by a 2D cell that will be split just after
9891                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9892                     ret3ptr[2*kk]=-(*it2+1);
9893                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9894                     ret3ptr[2*kk+1]=-(*it2+1);
9895                 }
9896             }
9897         }
9898       m1Desc->setCoords(ret1->getCoords());
9899       ret1NonCol->setCoords(ret1->getCoords());
9900       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9901       if(!outMesh2DSplit.empty())
9902         {
9903           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9904           for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9905             (*itt)->setCoords(da);
9906         }
9907     }
9908   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9909   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9910     {
9911       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9912       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9913       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9914       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9915       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9916       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));
9917       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9918       outMesh2DSplit.push_back(splitOfOneCell);
9919       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9920         ret2->pushBackSilent(*it);
9921     }
9922   //
9923   std::size_t nbOfMeshes(outMesh2DSplit.size());
9924   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9925   for(std::size_t i=0;i<nbOfMeshes;i++)
9926     tmp[i]=outMesh2DSplit[i];
9927   //
9928   ret1->getCoords()->setInfoOnComponents(compNames);
9929   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9930   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9931   ret3->rearrange(1);
9932   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9933   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9934     {
9935       int old2DCellId(-ret3->getIJ(*it,0)-1);
9936       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9937       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
9938     }
9939   ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9940   ret3->rearrange(2);
9941   //
9942   splitMesh1D=ret1.retn();
9943   splitMesh2D=ret2D.retn();
9944   cellIdInMesh2D=ret2.retn();
9945   cellIdInMesh1D=ret3.retn();
9946 }
9947
9948 /**
9949  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9950  * (newly created) nodes corresponding to the edge intersections.
9951  * Output params:
9952  * @param[out] cr, crI connectivity of the resulting mesh
9953  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9954  * TODO: describe input parameters
9955  */
9956 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9957                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9958                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9959                                                          const std::vector<double>& addCoords,
9960                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9961 {
9962   static const int SPACEDIM=2;
9963   const double *coo1(m1->getCoords()->getConstPointer());
9964   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9965   int offset1(m1->getNumberOfNodes());
9966   const double *coo2(m2->getCoords()->getConstPointer());
9967   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9968   int offset2(offset1+m2->getNumberOfNodes());
9969   int offset3(offset2+((int)addCoords.size())/2);
9970   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9971   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9972   // Here a BBTree on 2D-cells, not on segments:
9973   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9974   int ncell1(m1->getNumberOfCells());
9975   crI.push_back(0);
9976   for(int i=0;i<ncell1;i++)
9977     {
9978       std::vector<int> candidates2;
9979       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9980       std::map<INTERP_KERNEL::Node *,int> mapp;
9981       std::map<int,INTERP_KERNEL::Node *> mappRev;
9982       INTERP_KERNEL::QuadraticPolygon pol1;
9983       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9984       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9985       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9986       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9987       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9988       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9989           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9990       //
9991       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
9992       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9993       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9994       for(it1.first();!it1.finished();it1.next())
9995         edges1.insert(it1.current()->getPtr());
9996       //
9997       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9998       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9999       int ii=0;
10000       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10001         {
10002           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10003           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10004           // Complete mapping with elements coming from the current cell it2 in mesh2:
10005           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10006           // pol2 is the new QP in the final merged result.
10007           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10008               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10009         }
10010       ii=0;
10011       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10012         {
10013           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10014           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10015           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10016           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10017         }
10018       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10019       // by m2 but that we still want to keep in the final result.
10020       if(!edges1.empty())
10021         {
10022           try
10023           {
10024               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10025           }
10026           catch(INTERP_KERNEL::Exception& e)
10027           {
10028               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();
10029               throw INTERP_KERNEL::Exception(oss.str().c_str());
10030           }
10031         }
10032       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10033         (*it).second->decrRef();
10034     }
10035 }
10036
10037 /**
10038  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10039  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10040  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10041  * The caller is to deal with the resulting DataArrayInt.
10042  *  \throw If the coordinate array is not set.
10043  *  \throw If the nodal connectivity of the cells is not defined.
10044  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10045  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10046  *
10047  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10048  */
10049 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10050 {
10051   checkFullyDefined();
10052   if(getMeshDimension()!=1)
10053     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10054
10055   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10056   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10057   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10058   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10059   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10060   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10061   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10062   const int * dsi(_dsi->getConstPointer());
10063   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10064   m_points=0;
10065   if (dsii->getNumberOfTuples())
10066     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10067
10068   int nc(getNumberOfCells());
10069   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10070   result->alloc(nc,1);
10071
10072   // set of edges not used so far
10073   std::set<int> edgeSet;
10074   for (int i=0; i<nc; edgeSet.insert(i), i++);
10075
10076   int startSeg=0;
10077   int newIdx=0;
10078   // while we have points with only one neighbor segments
10079   do
10080     {
10081       std::list<int> linePiece;
10082       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10083       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10084         {
10085           // Fill the list forward (resp. backward) from the start segment:
10086           int activeSeg = startSeg;
10087           int prevPointId = -20;
10088           int ptId;
10089           while (!edgeSet.empty())
10090             {
10091               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10092                 {
10093                   if (direction==0)
10094                     linePiece.push_back(activeSeg);
10095                   else
10096                     linePiece.push_front(activeSeg);
10097                   edgeSet.erase(activeSeg);
10098                 }
10099
10100               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10101               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10102               if (dsi[ptId] == 1) // hitting the end of the line
10103                 break;
10104               prevPointId = ptId;
10105               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10106               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10107             }
10108         }
10109       // Done, save final piece into DA:
10110       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10111       newIdx += linePiece.size();
10112
10113       // identify next valid start segment (one which is not consumed)
10114       if(!edgeSet.empty())
10115         startSeg = *(edgeSet.begin());
10116     }
10117   while (!edgeSet.empty());
10118   return result.retn();
10119 }
10120
10121 /// @cond INTERNAL
10122
10123 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10124 {
10125   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10126   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10127   if(it==m.end())
10128     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10129   int v((*it).second);
10130   if(v==forbVal0 || v==forbVal1)
10131     return ;
10132   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10133     isect.push_back(v);
10134 }
10135
10136 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10137 {
10138   int sz(c.size());
10139   if(sz<=1)
10140     return false;
10141   bool presenceOfOn(false);
10142   for(int i=0;i<sz;i++)
10143     {
10144       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10145       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10146         continue ;
10147       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10148       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10149     }
10150   return presenceOfOn;
10151 }
10152
10153 /// @endcond
10154
10155 /**
10156  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10157  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10158  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10159  * a minimal creation of new nodes is wanted.
10160  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10161  * nodes if a SEG3 is split without information of middle.
10162  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10163  * avoid to have a non conform mesh.
10164  *
10165  * \return int - the number of new nodes created (in most of cases 0).
10166  * 
10167  * \throw If \a this is not coherent.
10168  * \throw If \a this has not spaceDim equal to 2.
10169  * \throw If \a this has not meshDim equal to 2.
10170  * \throw If some subcells needed to be split are orphan.
10171  * \sa MEDCouplingUMesh::conformize2D
10172  */
10173 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10174 {
10175   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10176     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10177   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10178   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10179     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10180   if(midOpt==0 && midOptI==0)
10181     {
10182       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10183       return 0;
10184     }
10185   else if(midOpt!=0 && midOptI!=0)
10186     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10187   else
10188     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10189 }
10190
10191 /*!
10192  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10193  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10194  * 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
10195  * 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).
10196  * 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.
10197  * 
10198  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10199  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10200  *
10201  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10202  * This method expects that all nodes in \a this are not closer than \a eps.
10203  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10204  * 
10205  * \param [in] eps the relative error to detect merged edges.
10206  * \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
10207  *                           that the user is expected to deal with.
10208  *
10209  * \throw If \a this is not coherent.
10210  * \throw If \a this has not spaceDim equal to 2.
10211  * \throw If \a this has not meshDim equal to 2.
10212  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10213  */
10214 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10215 {
10216   static const int SPACEDIM=2;
10217   checkCoherency();
10218   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10219     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10220   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10221   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10222   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10223   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10224   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10225   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10226   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10227   std::vector<double> addCoo;
10228   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10229   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10230   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10231   for(int i=0;i<nDescCell;i++)
10232     {
10233       std::vector<int> candidates;
10234       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10235       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10236         if(*it>i)
10237           {
10238             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10239             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10240                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10241             INTERP_KERNEL::MergePoints merge;
10242             INTERP_KERNEL::QuadraticPolygon c1,c2;
10243             e1->intersectWith(e2,merge,c1,c2);
10244             e1->decrRef(); e2->decrRef();
10245             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10246               overlapEdge[i].push_back(*it);
10247             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10248               overlapEdge[*it].push_back(i);
10249           }
10250     }
10251   // splitting done. sort intersect point in intersectEdge.
10252   std::vector< std::vector<int> > middle(nDescCell);
10253   int nbOf2DCellsToBeSplit(0);
10254   bool middleNeedsToBeUsed(false);
10255   std::vector<bool> cells2DToTreat(nDescCell,false);
10256   for(int i=0;i<nDescCell;i++)
10257     {
10258       std::vector<int>& isect(intersectEdge[i]);
10259       int sz((int)isect.size());
10260       if(sz>1)
10261         {
10262           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10263           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10264           e->sortSubNodesAbs(coords,isect);
10265           e->decrRef();
10266         }
10267       if(sz!=0)
10268         {
10269           int idx0(rdi[i]),idx1(rdi[i+1]);
10270           if(idx1-idx0!=1)
10271             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10272           if(!cells2DToTreat[rd[idx0]])
10273             {
10274               cells2DToTreat[rd[idx0]]=true;
10275               nbOf2DCellsToBeSplit++;
10276             }
10277           // try to reuse at most eventual 'middle' of SEG3
10278           std::vector<int>& mid(middle[i]);
10279           mid.resize(sz+1,-1);
10280           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10281             {
10282               middleNeedsToBeUsed=true;
10283               const std::vector<int>& candidates(overlapEdge[i]);
10284               std::vector<int> trueCandidates;
10285               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10286                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10287                   trueCandidates.push_back(*itc);
10288               int stNode(c[ci[i]+1]),endNode(isect[0]);
10289               for(int j=0;j<sz+1;j++)
10290                 {
10291                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10292                     {
10293                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10294                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10295                         { mid[j]=*itc; break; }
10296                     }
10297                   stNode=endNode;
10298                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10299                 }
10300             }
10301         }
10302     }
10303   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10304   if(nbOf2DCellsToBeSplit==0)
10305     return ret.retn();
10306   //
10307   int *retPtr(ret->getPointer());
10308   for(int i=0;i<nCell;i++)
10309     if(cells2DToTreat[i])
10310       *retPtr++=i;
10311   //
10312   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10313   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10314   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10315   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10316   if(middleNeedsToBeUsed)
10317     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10318   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10319   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10320   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.
10321   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10322   {
10323     bool areNodesMerged; int newNbOfNodes;
10324     if(nbOfNodesCreated!=0)
10325       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10326   }
10327   return ret.retn();
10328 }
10329
10330 /*!
10331  * 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.
10332  * 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).
10333  * 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
10334  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10335  * 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
10336  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10337  *
10338  * 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
10339  * using new instance, idem for coordinates.
10340  *
10341  * 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.
10342  * 
10343  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10344  *
10345  * \throw If \a this is not coherent.
10346  * \throw If \a this has not spaceDim equal to 2.
10347  * \throw If \a this has not meshDim equal to 2.
10348  * 
10349  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10350  */
10351 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10352 {
10353   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10354   checkCoherency();
10355   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10356     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10357   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10358   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10359   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10360   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10362   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10363   const double *coords(_coords->begin());
10364   int *newciptr(newci->getPointer());
10365   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10366     {
10367       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10368         ret->pushBackSilent(i);
10369       newciptr[1]=newc->getNumberOfTuples();
10370     }
10371   //
10372   if(ret->empty())
10373     return ret.retn();
10374   if(!appendedCoords->empty())
10375     {
10376       appendedCoords->rearrange(2);
10377       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10378       //non const part
10379       setCoords(newCoords);
10380     }
10381   //non const part
10382   setConnectivity(newc,newci,true);
10383   return ret.retn();
10384 }
10385
10386 /*!
10387  * \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.
10388  *                               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.
10389  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10390  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10391  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10392  * \param [out] addCoo - nodes to be append at the end
10393  * \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.
10394  */
10395 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10396                                          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)
10397 {
10398   static const int SPACEDIM=2;
10399   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10400   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10401   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10402   // Build BB tree of all edges in the tool mesh (second mesh)
10403   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10404   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10405   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10406   intersectEdge1.resize(nDescCell1);
10407   colinear2.resize(nDescCell2);
10408   subDiv2.resize(nDescCell2);
10409   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10410
10411   std::vector<int> candidates1(1);
10412   int offset1(m1Desc->getNumberOfNodes());
10413   int offset2(offset1+m2Desc->getNumberOfNodes());
10414   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10415     {
10416       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10417       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10418       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10419         {
10420           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10421           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10422           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10423           candidates1[0]=i;
10424           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10425           // 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
10426           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10427           std::set<INTERP_KERNEL::Node *> nodes;
10428           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10429           std::size_t szz(nodes.size());
10430           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10431           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10432           for(std::size_t iii=0;iii<szz;iii++,itt++)
10433             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10434           // end of protection
10435           // Performs egde cutting:
10436           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10437           delete pol2;
10438           delete pol1;
10439         }
10440       else
10441         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10442         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10443     }
10444 }
10445
10446 /*!
10447  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10448  * It builds the descending connectivity of the two meshes, and then using a binary tree
10449  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10450  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10451  */
10452 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10453                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10454                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10455                                                    std::vector<double>& addCoo,
10456                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10457 {
10458   // Build desc connectivity
10459   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10460   desc2=DataArrayInt::New();
10461   descIndx2=DataArrayInt::New();
10462   revDesc2=DataArrayInt::New();
10463   revDescIndx2=DataArrayInt::New();
10464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10466   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10467   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10468   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10469   std::map<int,int> notUsedMap;
10470   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10471   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10472   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10473 }
10474
10475 /*!
10476  * This method performs the 2nd step of Partition of 2D mesh.
10477  * This method has 4 inputs :
10478  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10479  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10480  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10481  * 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'
10482  * Nodes end up lying consecutively on a cutted edge.
10483  * \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.
10484  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10485  * \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.
10486  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10487  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10488  */
10489 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10490                                            const std::vector<double>& addCoo,
10491                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10492 {
10493   int offset1=m1->getNumberOfNodes();
10494   int ncell=m2->getNumberOfCells();
10495   const int *c=m2->getNodalConnectivity()->getConstPointer();
10496   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10497   const double *coo=m2->getCoords()->getConstPointer();
10498   const double *cooBis=m1->getCoords()->getConstPointer();
10499   int offset2=offset1+m2->getNumberOfNodes();
10500   intersectEdge.resize(ncell);
10501   for(int i=0;i<ncell;i++,cI++)
10502     {
10503       const std::vector<int>& divs=subDiv[i];
10504       int nnode=cI[1]-cI[0]-1;
10505       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10506       std::map<INTERP_KERNEL::Node *, int> mapp22;
10507       for(int j=0;j<nnode;j++)
10508         {
10509           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10510           int nnid=c[(*cI)+j+1];
10511           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10512           mapp22[nn]=nnid+offset1;
10513         }
10514       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10515       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10516         ((*it).second.first)->decrRef();
10517       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10518       std::map<INTERP_KERNEL::Node *,int> mapp3;
10519       for(std::size_t j=0;j<divs.size();j++)
10520         {
10521           int id=divs[j];
10522           INTERP_KERNEL::Node *tmp=0;
10523           if(id<offset1)
10524             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10525           else if(id<offset2)
10526             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10527           else
10528             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10529           addNodes[j]=tmp;
10530           mapp3[tmp]=id;
10531         }
10532       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10533       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10534         (*it)->decrRef();
10535       e->decrRef();
10536     }
10537 }
10538
10539 /*!
10540  * 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).
10541  * 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
10542  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10543  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10544  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10545  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10546  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10547  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10548  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10549  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10550  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10551  * \param [out] cut3DSuf input/output param.
10552  */
10553 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10554                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10555                                                    const int *desc, const int *descIndx, 
10556                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10557 {
10558   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10559   int nbOf3DSurfCell=(int)cut3DSurf.size();
10560   for(int i=0;i<nbOf3DSurfCell;i++)
10561     {
10562       std::vector<int> res;
10563       int offset=descIndx[i];
10564       int nbOfSeg=descIndx[i+1]-offset;
10565       for(int j=0;j<nbOfSeg;j++)
10566         {
10567           int edgeId=desc[offset+j];
10568           int status=cut3DCurve[edgeId];
10569           if(status!=-2)
10570             {
10571               if(status>-1)
10572                 res.push_back(status);
10573               else
10574                 {
10575                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10576                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10577                 }
10578             }
10579         }
10580       switch(res.size())
10581       {
10582         case 2:
10583           {
10584             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10585             break;
10586           }
10587         case 1:
10588         case 0:
10589           {
10590             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10591             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10592             if(res.size()==2)
10593               {
10594                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10595               }
10596             else
10597               {
10598                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10599               }
10600             break;
10601           }
10602         default:
10603           {// case when plane is on a multi colinear edge of a polyhedron
10604             if((int)res.size()==2*nbOfSeg)
10605               {
10606                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10607               }
10608             else
10609               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10610           }
10611       }
10612     }
10613 }
10614
10615 /*!
10616  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10617  * 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).
10618  * 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
10619  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10620  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10621  * \param desc is the descending connectivity 3D->3DSurf
10622  * \param descIndx is the descending connectivity index 3D->3DSurf
10623  */
10624 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10625                                                   const int *desc, const int *descIndx,
10626                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10627 {
10628   checkFullyDefined();
10629   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10630     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10631   const int *nodal3D=_nodal_connec->getConstPointer();
10632   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10633   int nbOfCells=getNumberOfCells();
10634   for(int i=0;i<nbOfCells;i++)
10635     {
10636       std::map<int, std::set<int> > m;
10637       int offset=descIndx[i];
10638       int nbOfFaces=descIndx[i+1]-offset;
10639       int start=-1;
10640       int end=-1;
10641       for(int j=0;j<nbOfFaces;j++)
10642         {
10643           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10644           if(p.first!=-1 && p.second!=-1)
10645             {
10646               if(p.first!=-2)
10647                 {
10648                   start=p.first; end=p.second;
10649                   m[p.first].insert(p.second);
10650                   m[p.second].insert(p.first);
10651                 }
10652               else
10653                 {
10654                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10655                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10656                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10657                   INTERP_KERNEL::NormalizedCellType cmsId;
10658                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10659                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10660                   for(unsigned k=0;k<nbOfNodesSon;k++)
10661                     {
10662                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10663                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10664                     }
10665                 }
10666             }
10667         }
10668       if(m.empty())
10669         continue;
10670       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10671       int prev=end;
10672       while(end!=start)
10673         {
10674           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10675           const std::set<int>& s=(*it).second;
10676           std::set<int> s2; s2.insert(prev);
10677           std::set<int> s3;
10678           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10679           if(s3.size()==1)
10680             {
10681               int val=*s3.begin();
10682               conn.push_back(start);
10683               prev=start;
10684               start=val;
10685             }
10686           else
10687             start=end;
10688         }
10689       conn.push_back(end);
10690       if(conn.size()>3)
10691         {
10692           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10693           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10694           cellIds->pushBackSilent(i);
10695         }
10696     }
10697 }
10698
10699 /*!
10700  * 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
10701  * 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
10702  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10703  * 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
10704  * 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.
10705  * 
10706  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10707  */
10708 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10709 {
10710   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10711   if(sz>=4)
10712     {
10713       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10714       if(cm.getDimension()==2)
10715         {
10716           const int *node=nodalConnBg+1;
10717           int startNode=*node++;
10718           double refX=coords[2*startNode];
10719           for(;node!=nodalConnEnd;node++)
10720             {
10721               if(coords[2*(*node)]<refX)
10722                 {
10723                   startNode=*node;
10724                   refX=coords[2*startNode];
10725                 }
10726             }
10727           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10728           refX=1e300;
10729           double tmp1;
10730           double tmp2[2];
10731           double angle0=-M_PI/2;
10732           //
10733           int nextNode=-1;
10734           int prevNode=-1;
10735           double resRef;
10736           double angleNext=0.;
10737           while(nextNode!=startNode)
10738             {
10739               nextNode=-1;
10740               resRef=1e300;
10741               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10742                 {
10743                   if(*node!=tmpOut.back() && *node!=prevNode)
10744                     {
10745                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10746                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10747                       double res;
10748                       if(angleM<=angle0)
10749                         res=angle0-angleM;
10750                       else
10751                         res=angle0-angleM+2.*M_PI;
10752                       if(res<resRef)
10753                         {
10754                           nextNode=*node;
10755                           resRef=res;
10756                           angleNext=angleM;
10757                         }
10758                     }
10759                 }
10760               if(nextNode!=startNode)
10761                 {
10762                   angle0=angleNext-M_PI;
10763                   if(angle0<-M_PI)
10764                     angle0+=2*M_PI;
10765                   prevNode=tmpOut.back();
10766                   tmpOut.push_back(nextNode);
10767                 }
10768             }
10769           std::vector<int> tmp3(2*(sz-1));
10770           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10771           std::copy(nodalConnBg+1,nodalConnEnd,it);
10772           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10773             {
10774               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10775               return false;
10776             }
10777           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10778             {
10779               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10780               return false;
10781             }
10782           else
10783             {
10784               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10785               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10786               return true;
10787             }
10788         }
10789       else
10790         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10791     }
10792   else
10793     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10794 }
10795
10796 /*!
10797  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10798  * 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.
10799  * 
10800  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10801  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10802  * \param [in,out] arr array in which the remove operation will be done.
10803  * \param [in,out] arrIndx array in the remove operation will modify
10804  * \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])
10805  * \return true if \b arr and \b arrIndx have been modified, false if not.
10806  */
10807 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10808 {
10809   if(!arrIndx || !arr)
10810     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10811   if(offsetForRemoval<0)
10812     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10813   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10814   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10815   int *arrIPtr=arrIndx->getPointer();
10816   *arrIPtr++=0;
10817   int previousArrI=0;
10818   const int *arrPtr=arr->getConstPointer();
10819   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10820   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10821     {
10822       if(*arrIPtr-previousArrI>offsetForRemoval)
10823         {
10824           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10825             {
10826               if(s.find(*work)==s.end())
10827                 arrOut.push_back(*work);
10828             }
10829         }
10830       previousArrI=*arrIPtr;
10831       *arrIPtr=(int)arrOut.size();
10832     }
10833   if(arr->getNumberOfTuples()==(int)arrOut.size())
10834     return false;
10835   arr->alloc((int)arrOut.size(),1);
10836   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10837   return true;
10838 }
10839
10840 /*!
10841  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10842  * (\ref numbering-indirect).
10843  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10844  * The selection of extraction is done standardly in new2old format.
10845  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10846  *
10847  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10848  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10849  * \param [in] arrIn arr origin array from which the extraction will be done.
10850  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10851  * \param [out] arrOut the resulting array
10852  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10853  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10854  */
10855 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10856                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10857 {
10858   if(!arrIn || !arrIndxIn)
10859     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10860   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10861   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10862     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10863   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10864   const int *arrInPtr=arrIn->getConstPointer();
10865   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10866   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10867   if(nbOfGrps<0)
10868     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10869   int maxSizeOfArr=arrIn->getNumberOfTuples();
10870   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10871   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10872   arrIo->alloc((int)(sz+1),1);
10873   const int *idsIt=idsOfSelectBg;
10874   int *work=arrIo->getPointer();
10875   *work++=0;
10876   int lgth=0;
10877   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10878     {
10879       if(*idsIt>=0 && *idsIt<nbOfGrps)
10880         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10881       else
10882         {
10883           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10884           throw INTERP_KERNEL::Exception(oss.str().c_str());
10885         }
10886       if(lgth>=work[-1])
10887         *work=lgth;
10888       else
10889         {
10890           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10891           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10892           throw INTERP_KERNEL::Exception(oss.str().c_str());
10893         }
10894     }
10895   arro->alloc(lgth,1);
10896   work=arro->getPointer();
10897   idsIt=idsOfSelectBg;
10898   for(std::size_t i=0;i<sz;i++,idsIt++)
10899     {
10900       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10901         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10902       else
10903         {
10904           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10905           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10906           throw INTERP_KERNEL::Exception(oss.str().c_str());
10907         }
10908     }
10909   arrOut=arro.retn();
10910   arrIndexOut=arrIo.retn();
10911 }
10912
10913 /*!
10914  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10915  * (\ref numbering-indirect).
10916  * 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 ).
10917  * The selection of extraction is done standardly in new2old format.
10918  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10919  *
10920  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
10921  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
10922  * \param [in] idsOfSelectStep
10923  * \param [in] arrIn arr origin array from which the extraction will be done.
10924  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10925  * \param [out] arrOut the resulting array
10926  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10927  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10928  */
10929 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10930                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10931 {
10932   if(!arrIn || !arrIndxIn)
10933     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10934   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10935   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10936     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10937   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10938   const int *arrInPtr=arrIn->getConstPointer();
10939   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10940   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10941   if(nbOfGrps<0)
10942     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10943   int maxSizeOfArr=arrIn->getNumberOfTuples();
10944   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10945   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10946   arrIo->alloc((int)(sz+1),1);
10947   int idsIt=idsOfSelectStart;
10948   int *work=arrIo->getPointer();
10949   *work++=0;
10950   int lgth=0;
10951   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10952     {
10953       if(idsIt>=0 && idsIt<nbOfGrps)
10954         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10955       else
10956         {
10957           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10958           throw INTERP_KERNEL::Exception(oss.str().c_str());
10959         }
10960       if(lgth>=work[-1])
10961         *work=lgth;
10962       else
10963         {
10964           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10965           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10966           throw INTERP_KERNEL::Exception(oss.str().c_str());
10967         }
10968     }
10969   arro->alloc(lgth,1);
10970   work=arro->getPointer();
10971   idsIt=idsOfSelectStart;
10972   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10973     {
10974       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10975         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10976       else
10977         {
10978           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10979           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10980           throw INTERP_KERNEL::Exception(oss.str().c_str());
10981         }
10982     }
10983   arrOut=arro.retn();
10984   arrIndexOut=arrIo.retn();
10985 }
10986
10987 /*!
10988  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10989  * 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
10990  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10991  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10992  *
10993  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10994  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10995  * \param [in] arrIn arr origin array from which the extraction will be done.
10996  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10997  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10998  * \param [in] srcArrIndex index array of \b srcArr
10999  * \param [out] arrOut the resulting array
11000  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11001  * 
11002  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11003  */
11004 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11005                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11006                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11007 {
11008   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11009     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11010   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11011   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11012   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11013   std::vector<bool> v(nbOfTuples,true);
11014   int offset=0;
11015   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11016   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11017   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11018     {
11019       if(*it>=0 && *it<nbOfTuples)
11020         {
11021           v[*it]=false;
11022           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11023         }
11024       else
11025         {
11026           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11027           throw INTERP_KERNEL::Exception(oss.str().c_str());
11028         }
11029     }
11030   srcArrIndexPtr=srcArrIndex->getConstPointer();
11031   arrIo->alloc(nbOfTuples+1,1);
11032   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11033   const int *arrInPtr=arrIn->getConstPointer();
11034   const int *srcArrPtr=srcArr->getConstPointer();
11035   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11036   int *arroPtr=arro->getPointer();
11037   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11038     {
11039       if(v[ii])
11040         {
11041           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11042           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11043         }
11044       else
11045         {
11046           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11047           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11048           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11049         }
11050     }
11051   arrOut=arro.retn();
11052   arrIndexOut=arrIo.retn();
11053 }
11054
11055 /*!
11056  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11057  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11058  *
11059  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11060  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11061  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11062  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11063  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11064  * \param [in] srcArrIndex index array of \b srcArr
11065  * 
11066  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11067  */
11068 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11069                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11070 {
11071   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11072     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11073   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11074   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11075   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11076   int *arrInOutPtr=arrInOut->getPointer();
11077   const int *srcArrPtr=srcArr->getConstPointer();
11078   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11079     {
11080       if(*it>=0 && *it<nbOfTuples)
11081         {
11082           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11083             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11084           else
11085             {
11086               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] !";
11087               throw INTERP_KERNEL::Exception(oss.str().c_str());
11088             }
11089         }
11090       else
11091         {
11092           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11093           throw INTERP_KERNEL::Exception(oss.str().c_str());
11094         }
11095     }
11096 }
11097
11098 /*!
11099  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11100  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11101  * 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]].
11102  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11103  * A negative value in \b arrIn means that it is ignored.
11104  * 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.
11105  * 
11106  * \param [in] arrIn arr origin array from which the extraction will be done.
11107  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11108  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11109  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11110  */
11111 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11112 {
11113   int seed=0,nbOfDepthPeelingPerformed=0;
11114   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11115 }
11116
11117 /*!
11118  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11119  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11120  * 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]].
11121  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11122  * A negative value in \b arrIn means that it is ignored.
11123  * 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.
11124  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11125  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11126  * \param [in] arrIn arr origin array from which the extraction will be done.
11127  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11128  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11129  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11130  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11131  * \sa MEDCouplingUMesh::partitionBySpreadZone
11132  */
11133 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11134 {
11135   nbOfDepthPeelingPerformed=0;
11136   if(!arrIndxIn)
11137     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11138   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11139   if(nbOfTuples<=0)
11140     {
11141       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11142       return ret;
11143     }
11144   //
11145   std::vector<bool> fetched(nbOfTuples,false);
11146   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11147 }
11148
11149 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11150 {
11151   nbOfDepthPeelingPerformed=0;
11152   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11153     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11154   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11155   std::vector<bool> fetched2(nbOfTuples,false);
11156   int i=0;
11157   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11158     {
11159       if(*seedElt>=0 && *seedElt<nbOfTuples)
11160         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11161       else
11162         { 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()); }
11163     }
11164   const int *arrInPtr=arrIn->getConstPointer();
11165   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11166   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11167   std::vector<int> idsToFetch1(seedBg,seedEnd);
11168   std::vector<int> idsToFetch2;
11169   std::vector<int> *idsToFetch=&idsToFetch1;
11170   std::vector<int> *idsToFetchOther=&idsToFetch2;
11171   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11172     {
11173       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11174         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11175           if(!fetched[*it2])
11176             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11177       std::swap(idsToFetch,idsToFetchOther);
11178       idsToFetchOther->clear();
11179       nbOfDepthPeelingPerformed++;
11180     }
11181   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11182   i=0;
11183   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11184   int *retPtr=ret->getPointer();
11185   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11186     if(*it)
11187       *retPtr++=i;
11188   return ret.retn();
11189 }
11190
11191 /*!
11192  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11193  * 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
11194  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11195  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11196  *
11197  * \param [in] start begin of set of ids of the input extraction (included)
11198  * \param [in] end end of set of ids of the input extraction (excluded)
11199  * \param [in] step step of the set of ids in range mode.
11200  * \param [in] arrIn arr origin array from which the extraction will be done.
11201  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11202  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11203  * \param [in] srcArrIndex index array of \b srcArr
11204  * \param [out] arrOut the resulting array
11205  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11206  * 
11207  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11208  */
11209 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11210                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11211                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11212 {
11213   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11214     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11215   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11216   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11217   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11218   int offset=0;
11219   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11220   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11221   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11222   int it=start;
11223   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11224     {
11225       if(it>=0 && it<nbOfTuples)
11226         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11227       else
11228         {
11229           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11230           throw INTERP_KERNEL::Exception(oss.str().c_str());
11231         }
11232     }
11233   srcArrIndexPtr=srcArrIndex->getConstPointer();
11234   arrIo->alloc(nbOfTuples+1,1);
11235   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11236   const int *arrInPtr=arrIn->getConstPointer();
11237   const int *srcArrPtr=srcArr->getConstPointer();
11238   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11239   int *arroPtr=arro->getPointer();
11240   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11241     {
11242       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11243       if(pos<0)
11244         {
11245           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11246           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11247         }
11248       else
11249         {
11250           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11251           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11252         }
11253     }
11254   arrOut=arro.retn();
11255   arrIndexOut=arrIo.retn();
11256 }
11257
11258 /*!
11259  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11260  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11261  *
11262  * \param [in] start begin of set of ids of the input extraction (included)
11263  * \param [in] end end of set of ids of the input extraction (excluded)
11264  * \param [in] step step of the set of ids in range mode.
11265  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11266  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11267  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11268  * \param [in] srcArrIndex index array of \b srcArr
11269  * 
11270  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11271  */
11272 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11273                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11274 {
11275   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11276     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11277   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11278   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11279   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11280   int *arrInOutPtr=arrInOut->getPointer();
11281   const int *srcArrPtr=srcArr->getConstPointer();
11282   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11283   int it=start;
11284   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11285     {
11286       if(it>=0 && it<nbOfTuples)
11287         {
11288           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11289             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11290           else
11291             {
11292               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11293               throw INTERP_KERNEL::Exception(oss.str().c_str());
11294             }
11295         }
11296       else
11297         {
11298           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11299           throw INTERP_KERNEL::Exception(oss.str().c_str());
11300         }
11301     }
11302 }
11303
11304 /*!
11305  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11306  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11307  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11308  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11309  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11310  * 
11311  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11312  */
11313 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11314 {
11315   checkFullyDefined();
11316   int mdim=getMeshDimension();
11317   int spaceDim=getSpaceDimension();
11318   if(mdim!=spaceDim)
11319     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11320   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11321   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11322   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11323   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11324   ret->setCoords(getCoords());
11325   ret->allocateCells((int)partition.size());
11326   //
11327   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11328     {
11329       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11330       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11331       switch(mdim)
11332       {
11333         case 2:
11334           cell=tmp->buildUnionOf2DMesh();
11335           break;
11336         case 3:
11337           cell=tmp->buildUnionOf3DMesh();
11338           break;
11339         default:
11340           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11341       }
11342
11343       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11344     }
11345   //
11346   ret->finishInsertingCells();
11347   return ret.retn();
11348 }
11349
11350 /*!
11351  * This method partitions \b this into contiguous zone.
11352  * This method only needs a well defined connectivity. Coordinates are not considered here.
11353  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11354  */
11355 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11356 {
11357   int nbOfCellsCur=getNumberOfCells();
11358   std::vector<DataArrayInt *> ret;
11359   if(nbOfCellsCur<=0)
11360     return ret;
11361   DataArrayInt *neigh=0,*neighI=0;
11362   computeNeighborsOfCells(neigh,neighI);
11363   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11364   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11365   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11366   int seed=0;
11367   while(seed<nbOfCellsCur)
11368     {
11369       int nbOfPeelPerformed=0;
11370       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11371       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11372     }
11373   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11374     ret.push_back((*it).retn());
11375   return ret;
11376 }
11377
11378 /*!
11379  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11380  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11381  *
11382  * \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.
11383  * \return a newly allocated DataArrayInt to be managed by the caller.
11384  * \throw In case of \a code has not the right format (typically of size 3*n)
11385  */
11386 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11387 {
11388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11389   std::size_t nb=code.size()/3;
11390   if(code.size()%3!=0)
11391     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11392   ret->alloc((int)nb,2);
11393   int *retPtr=ret->getPointer();
11394   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11395     {
11396       retPtr[0]=code[3*i+2];
11397       retPtr[1]=code[3*i+2]+code[3*i+1];
11398     }
11399   return ret.retn();
11400 }
11401
11402 /*!
11403  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11404  * All cells in \a this are expected to be linear 3D cells.
11405  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11406  * It leads to an increase to number of cells.
11407  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11408  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11409  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11410  *
11411  * \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.
11412  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11413  * \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. 
11414  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11415  *          an id of old cell producing it. The caller is to delete this array using
11416  *         decrRef() as it is no more needed.
11417  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11418  *
11419  * \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
11420  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11421  * 
11422  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11423  * \throw If \a this is not fully constituted with linear 3D cells.
11424  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11425  */
11426 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11427 {
11428   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11429   checkConnectivityFullyDefined();
11430   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11431     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11432   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11433   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11434   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11435   int *retPt(ret->getPointer());
11436   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11437   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11438   const int *oldc(_nodal_connec->begin());
11439   const int *oldci(_nodal_connec_index->begin());
11440   const double *coords(_coords->begin());
11441   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11442     {
11443       std::vector<int> a; std::vector<double> b;
11444       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11445       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11446       const int *aa(&a[0]);
11447       if(!b.empty())
11448         {
11449           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11450             if(*it<0)
11451               *it=(-(*(it))-1+nbNodes);
11452           addPts->insertAtTheEnd(b.begin(),b.end());
11453           nbNodes+=(int)b.size()/3;
11454         }
11455       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11456         newConn->insertAtTheEnd(aa,aa+4);
11457     }
11458   if(!addPts->empty())
11459     {
11460       addPts->rearrange(3);
11461       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11462       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11463       ret0->setCoords(addPts);
11464     }
11465   else
11466     {
11467       nbOfAdditionalPoints=0;
11468       ret0->setCoords(getCoords());
11469     }
11470   ret0->setNodalConnectivity(newConn);
11471   //
11472   ret->computeOffsets2();
11473   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11474   return ret0.retn();
11475 }
11476
11477 /*!
11478  * 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). 
11479  *
11480  * \sa MEDCouplingUMesh::split2DCells
11481  */
11482 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11483 {
11484   checkConnectivityFullyDefined();
11485   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11486   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11487   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11488   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11489   int prevPosOfCi(ciPtr[0]);
11490   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11491     {
11492       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11493       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11494       for(int j=0;j<sz;j++)
11495         {
11496           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11497           for(int k=0;k<sz2;k++)
11498             *cPtr++=subPtr[offset2+k];
11499           if(j!=sz-1)
11500             *cPtr++=oldConn[prevPosOfCi+j+2];
11501           deltaSz+=sz2;
11502         }
11503       prevPosOfCi=ciPtr[1];
11504       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11505     }
11506   if(c->end()!=cPtr)
11507     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11508   _nodal_connec->decrRef();
11509   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11510 }
11511
11512 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11513 {
11514   if(id!=-1)
11515     return id;
11516   else
11517     {
11518       int ret(nodesCnter++);
11519       double newPt[2];
11520       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11521       addCoo.insertAtTheEnd(newPt,newPt+2);
11522       return ret;
11523     }
11524 }
11525
11526 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11527 {
11528   if(id!=-1)
11529     return id;
11530   else
11531     {
11532       int ret(nodesCnter++);
11533       double newPt[2];
11534       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11535       addCoo.insertAtTheEnd(newPt,newPt+2);
11536       return ret;
11537     }
11538 }
11539
11540
11541 /// @cond INTERNAL
11542
11543 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)
11544 {
11545   int tmp[3];
11546   int trueStart(start>=0?start:nbOfEdges+start);
11547   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11548   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11549   if(linOrArc)
11550     {
11551       if(stp-start>1)
11552         {
11553           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11554           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11555           middles.push_back(tmp3+offset);
11556         }
11557       else
11558         middles.push_back(connBg[trueStart+nbOfEdges]);
11559     }
11560 }
11561
11562 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)
11563 {
11564   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11565   newConnOfCell->pushBackSilent(tmpEnd);
11566   if(linOrArc)
11567     {
11568       if(stp-start>1)
11569         {
11570           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11571           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11572           middles.push_back(tmp3+offset);
11573         }
11574       else
11575         middles.push_back(connBg[start+nbOfEdges]);
11576     }
11577 }
11578
11579 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)
11580 {
11581   // only the quadratic point to deal with:
11582   if(linOrArc)
11583     {
11584       if(stp-start>1)
11585         {
11586           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11587           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11588           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11589           middles.push_back(tmp3+offset);
11590         }
11591       else
11592         middles.push_back(connBg[start+nbOfEdges]);
11593     }
11594 }
11595
11596 /// @endcond
11597
11598 /*!
11599  * 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 ) .
11600  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11601  */
11602 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11603 {
11604   std::size_t sz(std::distance(connBg,connEnd));
11605   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11606     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11607   sz--;
11608   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11609   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11610   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11611   unsigned nbOfHit(0); // number of fusions operated
11612   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11613   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
11614   INTERP_KERNEL::NormalizedCellType typeOfSon;
11615   std::vector<int> middles;
11616   bool ret(false);
11617   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11618     {
11619       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11620       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11621       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11622       posEndElt = posBaseElt+1;
11623
11624       // Look backward first: are the final edges of the cells colinear with the first ones?
11625       // This initializes posBaseElt.
11626       if(nbOfTurn==0)
11627         {
11628           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11629             {
11630               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11631               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11632               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11633               bool isColinear=eint->areColinears();
11634               if(isColinear)
11635                 {
11636                   nbOfHit++;
11637                   posBaseElt--;
11638                   ret=true;
11639                 }
11640               delete eint;
11641               eCand->decrRef();
11642               if(!isColinear)
11643                 break;
11644             }
11645         }
11646       // Now move forward:
11647       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11648       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11649         {
11650           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11651           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11652           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11653           bool isColinear(eint->areColinears());
11654           if(isColinear)
11655             {
11656               nbOfHit++;
11657               posEndElt++;
11658               ret=true;
11659             }
11660           delete eint;
11661           eCand->decrRef();
11662           if(!isColinear)
11663               break;
11664         }
11665       //push [posBaseElt,posEndElt) in newConnOfCell using e
11666       // 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!
11667       if(nbOfTurn==0)
11668         // at the begining of the connectivity (insert type)
11669         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11670       else if((nbOfHit+nbOfTurn) != (nbs-1))
11671         // in the middle
11672         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11673       if ((nbOfHit+nbOfTurn) == (nbs-1))
11674         // at the end (only quad points to deal with)
11675         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11676       posBaseElt=posEndElt;
11677       e->decrRef();
11678     }
11679   if(!middles.empty())
11680     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11681   return ret;
11682 }
11683
11684 /*!
11685  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11686  *
11687  * \return  int - the number of new nodes created.
11688  * \sa MEDCouplingUMesh::split2DCells
11689  */
11690 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11691 {
11692   checkCoherency();
11693   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11694   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11695   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11696   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11697   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11698   const double *oldCoordsPtr(getCoords()->begin());
11699   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11700   int prevPosOfCi(ciPtr[0]);
11701   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11702     {
11703       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11704       for(int j=0;j<sz;j++)
11705         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11706       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11707       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11708         {
11709           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11710           if(sz2==0)
11711             {
11712               if(j<sz-1)
11713                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11714               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11715               continue;
11716             }
11717           std::vector<INTERP_KERNEL::Node *> ns(3);
11718           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11719           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11720           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11721           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11722           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11723             {
11724               cPtr[1]=subPtr[offset2+k];
11725               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11726             }
11727           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11728           if(j!=sz-1)
11729             { cPtr[1]=tmpEnd; }
11730           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11731         }
11732       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11733       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11734     }
11735   if(c->end()!=cPtr)
11736     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11737   _nodal_connec->decrRef();
11738   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11739   addCoo->rearrange(2);
11740   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11741   setCoords(coo);
11742   return addCoo->getNumberOfTuples();
11743 }
11744
11745 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11746 {
11747   if(nodalConnec && nodalConnecIndex)
11748     {
11749       types.clear();
11750       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11751       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11752       if(nbOfElem>0)
11753         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11754           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11755     }
11756 }
11757
11758 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11759     _own_cell(true),_cell_id(-1),_nb_cell(0)
11760 {
11761   if(mesh)
11762     {
11763       mesh->incrRef();
11764       _nb_cell=mesh->getNumberOfCells();
11765     }
11766 }
11767
11768 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11769 {
11770   if(_mesh)
11771     _mesh->decrRef();
11772   if(_own_cell)
11773     delete _cell;
11774 }
11775
11776 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11777     _own_cell(false),_cell_id(bg-1),
11778     _nb_cell(end)
11779 {
11780   if(mesh)
11781     mesh->incrRef();
11782 }
11783
11784 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11785 {
11786   _cell_id++;
11787   if(_cell_id<_nb_cell)
11788     {
11789       _cell->next();
11790       return _cell;
11791     }
11792   else
11793     return 0;
11794 }
11795
11796 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11797 {
11798   if(_mesh)
11799     _mesh->incrRef();
11800 }
11801
11802 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11803 {
11804   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11805 }
11806
11807 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11808 {
11809   if(_mesh)
11810     _mesh->decrRef();
11811 }
11812
11813 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11814     _itc(itc),
11815     _bg(bg),_end(end)
11816 {
11817   if(_mesh)
11818     _mesh->incrRef();
11819 }
11820
11821 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11822 {
11823   if(_mesh)
11824     _mesh->decrRef();
11825 }
11826
11827 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11828 {
11829   return _type;
11830 }
11831
11832 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11833 {
11834   return _end-_bg;
11835 }
11836
11837 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11838 {
11839   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11840 }
11841
11842 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11843 {
11844   if(mesh)
11845     {
11846       mesh->incrRef();
11847       _nb_cell=mesh->getNumberOfCells();
11848     }
11849 }
11850
11851 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11852 {
11853   if(_mesh)
11854     _mesh->decrRef();
11855   delete _cell;
11856 }
11857
11858 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11859 {
11860   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11861   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11862   if(_cell_id<_nb_cell)
11863     {
11864       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11865       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11866       int startId=_cell_id;
11867       _cell_id+=nbOfElems;
11868       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11869     }
11870   else
11871     return 0;
11872 }
11873
11874 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11875 {
11876   if(mesh)
11877     {
11878       _conn=mesh->getNodalConnectivity()->getPointer();
11879       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11880     }
11881 }
11882
11883 void MEDCouplingUMeshCell::next()
11884 {
11885   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11886     {
11887       _conn+=_conn_lgth;
11888       _conn_indx++;
11889     }
11890   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11891 }
11892
11893 std::string MEDCouplingUMeshCell::repr() const
11894 {
11895   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11896     {
11897       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11898       oss << " : ";
11899       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11900       return oss.str();
11901     }
11902   else
11903     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11904 }
11905
11906 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11907 {
11908   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11909     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11910   else
11911     return INTERP_KERNEL::NORM_ERROR;
11912 }
11913
11914 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11915 {
11916   lgth=_conn_lgth;
11917   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11918     return _conn;
11919   else
11920     return 0;
11921 }