Salome HOME
Let the power of orderConsecutiveCells1D express itself.
[modules/med.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2014  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 "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 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 };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 /*!
93  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94  * The coordinates are shared between \a this and the returned instance.
95  * 
96  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97  * \sa MEDCouplingUMesh::deepCpy
98  */
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
100 {
101   checkConnectivityFullyDefined();
102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104   ret->setConnectivity(c,ci);
105   return ret.retn();
106 }
107
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
109 {
110   if(!other)
111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
113   if(!otherC)
114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
117 }
118
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
120 {
121   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
122   return ret;
123 }
124
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
126 {
127   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
128   ret.push_back(_nodal_connec);
129   ret.push_back(_nodal_connec_index);
130   return ret;
131 }
132
133 void MEDCouplingUMesh::updateTime() const
134 {
135   MEDCouplingPointSet::updateTime();
136   if(_nodal_connec)
137     {
138       updateTimeWith(*_nodal_connec);
139     }
140   if(_nodal_connec_index)
141     {
142       updateTimeWith(*_nodal_connec_index);
143     }
144 }
145
146 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
147 {
148 }
149
150 /*!
151  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
152  * then \a this mesh is most probably is writable, exchangeable and available for most
153  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
154  * this method to check that all is in order with \a this mesh.
155  *  \throw If the mesh dimension is not set.
156  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
157  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
158  *  \throw If the connectivity data array has more than one component.
159  *  \throw If the connectivity data array has a named component.
160  *  \throw If the connectivity index data array has more than one component.
161  *  \throw If the connectivity index data array has a named component.
162  */
163 void MEDCouplingUMesh::checkCoherency() const
164 {
165   if(_mesh_dim<-1)
166     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
167   if(_mesh_dim!=-1)
168     MEDCouplingPointSet::checkCoherency();
169   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
170     {
171       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
172         {
173           std::ostringstream message;
174           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
175           throw INTERP_KERNEL::Exception(message.str().c_str());
176         }
177     }
178   if(_nodal_connec)
179     {
180       if(_nodal_connec->getNumberOfComponents()!=1)
181         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
182       if(_nodal_connec->getInfoOnComponent(0)!="")
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
184     }
185   else
186     if(_mesh_dim!=-1)
187       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
188   if(_nodal_connec_index)
189     {
190       if(_nodal_connec_index->getNumberOfComponents()!=1)
191         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
192       if(_nodal_connec_index->getInfoOnComponent(0)!="")
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
194     }
195   else
196     if(_mesh_dim!=-1)
197       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
198 }
199
200 /*!
201  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
202  * then \a this mesh is most probably is writable, exchangeable and available for all
203  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
204  * method thoroughly checks the nodal connectivity.
205  *  \param [in] eps - a not used parameter.
206  *  \throw If the mesh dimension is not set.
207  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
208  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
209  *  \throw If the connectivity data array has more than one component.
210  *  \throw If the connectivity data array has a named component.
211  *  \throw If the connectivity index data array has more than one component.
212  *  \throw If the connectivity index data array has a named component.
213  *  \throw If number of nodes defining an element does not correspond to the type of element.
214  *  \throw If the nodal connectivity includes an invalid node id.
215  */
216 void MEDCouplingUMesh::checkCoherency1(double eps) const
217 {
218   checkCoherency();
219   if(_mesh_dim==-1)
220     return ;
221   int meshDim=getMeshDimension();
222   int nbOfNodes=getNumberOfNodes();
223   int nbOfCells=getNumberOfCells();
224   const int *ptr=_nodal_connec->getConstPointer();
225   const int *ptrI=_nodal_connec_index->getConstPointer();
226   for(int i=0;i<nbOfCells;i++)
227     {
228       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
229       if((int)cm.getDimension()!=meshDim)
230         {
231           std::ostringstream oss;
232           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
233           throw INTERP_KERNEL::Exception(oss.str().c_str());
234         }
235       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
236       if(!cm.isDynamic())
237         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
238           {
239             std::ostringstream oss;
240             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
241             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
242             throw INTERP_KERNEL::Exception(oss.str().c_str());
243           }
244       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
245         {
246           int nodeId=*w;
247           if(nodeId>=0)
248             {
249               if(nodeId>=nbOfNodes)
250                 {
251                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
252                   throw INTERP_KERNEL::Exception(oss.str().c_str());
253                 }
254             }
255           else if(nodeId<-1)
256             {
257               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
258               throw INTERP_KERNEL::Exception(oss.str().c_str());
259             }
260           else
261             {
262               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
263                 {
264                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
265                   throw INTERP_KERNEL::Exception(oss.str().c_str());
266                 }
267             }
268         }
269     }
270 }
271
272
273 /*!
274  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
275  * then \a this mesh is most probably is writable, exchangeable and available for all
276  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
277  *  \param [in] eps - a not used parameter.
278  *  \throw If the mesh dimension is not set.
279  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
280  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
281  *  \throw If the connectivity data array has more than one component.
282  *  \throw If the connectivity data array has a named component.
283  *  \throw If the connectivity index data array has more than one component.
284  *  \throw If the connectivity index data array has a named component.
285  *  \throw If number of nodes defining an element does not correspond to the type of element.
286  *  \throw If the nodal connectivity includes an invalid node id.
287  */
288 void MEDCouplingUMesh::checkCoherency2(double eps) const
289 {
290   checkCoherency1(eps);
291 }
292
293 /*!
294  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
295  * elements contained in the mesh. For more info on the mesh dimension see
296  * \ref MEDCouplingUMeshPage.
297  *  \param [in] meshDim - a new mesh dimension.
298  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
299  */
300 void MEDCouplingUMesh::setMeshDimension(int meshDim)
301 {
302   if(meshDim<-1 || meshDim>3)
303     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
304   _mesh_dim=meshDim;
305   declareAsNew();
306 }
307
308 /*!
309  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
310  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
311  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
312  *
313  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
314  *
315  *  \if ENABLE_EXAMPLES
316  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
317  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
318  *  \endif
319  */
320 void MEDCouplingUMesh::allocateCells(int nbOfCells)
321 {
322   if(nbOfCells<0)
323     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
324   if(_nodal_connec_index)
325     {
326       _nodal_connec_index->decrRef();
327     }
328   if(_nodal_connec)
329     {
330       _nodal_connec->decrRef();
331     }
332   _nodal_connec_index=DataArrayInt::New();
333   _nodal_connec_index->reserve(nbOfCells+1);
334   _nodal_connec_index->pushBackSilent(0);
335   _nodal_connec=DataArrayInt::New();
336   _nodal_connec->reserve(2*nbOfCells);
337   _types.clear();
338   declareAsNew();
339 }
340
341 /*!
342  * Appends a cell to the connectivity array. For deeper understanding what is
343  * happening see \ref MEDCouplingUMeshNodalConnectivity.
344  *  \param [in] type - type of cell to add.
345  *  \param [in] size - number of nodes constituting this cell.
346  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
347  * 
348  *  \if ENABLE_EXAMPLES
349  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
350  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
351  *  \endif
352  */
353 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
354 {
355   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
356   if(_nodal_connec_index==0)
357     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
358   if((int)cm.getDimension()==_mesh_dim)
359     {
360       if(!cm.isDynamic())
361         if(size!=(int)cm.getNumberOfNodes())
362           {
363             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
364             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
365             throw INTERP_KERNEL::Exception(oss.str().c_str());
366           }
367       int idx=_nodal_connec_index->back();
368       int val=idx+size+1;
369       _nodal_connec_index->pushBackSilent(val);
370       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
371       _types.insert(type);
372     }
373   else
374     {
375       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
376       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
377       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
378       throw INTERP_KERNEL::Exception(oss.str().c_str());
379     }
380 }
381
382 /*!
383  * Compacts data arrays to release unused memory. This method is to be called after
384  * finishing cell insertion using \a this->insertNextCell().
385  * 
386  *  \if ENABLE_EXAMPLES
387  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
388  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
389  *  \endif
390  */
391 void MEDCouplingUMesh::finishInsertingCells()
392 {
393   _nodal_connec->pack();
394   _nodal_connec_index->pack();
395   _nodal_connec->declareAsNew();
396   _nodal_connec_index->declareAsNew();
397   updateTime();
398 }
399
400 /*!
401  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
402  * Useful for python users.
403  */
404 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
405 {
406   return new MEDCouplingUMeshCellIterator(this);
407 }
408
409 /*!
410  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
411  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
412  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
413  * Useful for python users.
414  */
415 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
416 {
417   if(!checkConsecutiveCellTypes())
418     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
419   return new MEDCouplingUMeshCellByTypeEntry(this);
420 }
421
422 /*!
423  * Returns a set of all cell types available in \a this mesh.
424  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
425  * \warning this method does not throw any exception even if \a this is not defined.
426  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
427  */
428 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
429 {
430   return _types;
431 }
432
433 /*!
434  * This method returns the sorted list of geometric types in \a this.
435  * 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
436  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
437  *
438  * \throw if connectivity in \a this is not correctly defined.
439  *  
440  * \sa MEDCouplingMesh::getAllGeoTypes
441  */
442 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
443 {
444   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
445   checkConnectivityFullyDefined();
446   int nbOfCells(getNumberOfCells());
447   if(nbOfCells==0)
448     return ret;
449   if(getMeshLength()<1)
450     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
451   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
452   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
453   for(int i=1;i<nbOfCells;i++,ci++)
454     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
455       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
456   return ret;
457 }
458
459 /*!
460  * This method is a method that compares \a this and \a other.
461  * This method compares \b all attributes, even names and component names.
462  */
463 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
464 {
465   if(!other)
466     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
467   std::ostringstream oss; oss.precision(15);
468   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
469   if(!otherC)
470     {
471       reason="mesh given in input is not castable in MEDCouplingUMesh !";
472       return false;
473     }
474   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
475     return false;
476   if(_mesh_dim!=otherC->_mesh_dim)
477     {
478       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
479       reason=oss.str();
480       return false;
481     }
482   if(_types!=otherC->_types)
483     {
484       oss << "umesh geometric type mismatch :\nThis geometric types are :";
485       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
486         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
487       oss << "\nOther geometric types are :";
488       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
489         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
490       reason=oss.str();
491       return false;
492     }
493   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
494     if(_nodal_connec==0 || otherC->_nodal_connec==0)
495       {
496         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
497         return false;
498       }
499   if(_nodal_connec!=otherC->_nodal_connec)
500     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
501       {
502         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
503         return false;
504       }
505   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
506     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
507       {
508         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
509         return false;
510       }
511   if(_nodal_connec_index!=otherC->_nodal_connec_index)
512     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
513       {
514         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
515         return false;
516       }
517   return true;
518 }
519
520 /*!
521  * Checks if data arrays of this mesh (node coordinates, nodal
522  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
523  * not considered.
524  *  \param [in] other - the mesh to compare with.
525  *  \param [in] prec - precision value used to compare node coordinates.
526  *  \return bool - \a true if the two meshes are same.
527  */
528 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
529 {
530   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
531   if(!otherC)
532     return false;
533   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
534     return false;
535   if(_mesh_dim!=otherC->_mesh_dim)
536     return false;
537   if(_types!=otherC->_types)
538     return false;
539   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
540     if(_nodal_connec==0 || otherC->_nodal_connec==0)
541       return false;
542   if(_nodal_connec!=otherC->_nodal_connec)
543     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
544       return false;
545   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
546     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
547       return false;
548   if(_nodal_connec_index!=otherC->_nodal_connec_index)
549     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
550       return false;
551   return true;
552 }
553
554 /*!
555  * Checks if \a this and \a other meshes are geometrically equivalent with high
556  * probability, else an exception is thrown. The meshes are considered equivalent if
557  * (1) meshes contain the same number of nodes and the same number of elements of the
558  * same types (2) three cells of the two meshes (first, last and middle) are based
559  * on coincident nodes (with a specified precision).
560  *  \param [in] other - the mesh to compare with.
561  *  \param [in] prec - the precision used to compare nodes of the two meshes.
562  *  \throw If the two meshes do not match.
563  */
564 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
565 {
566   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
567   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
568   if(!otherC)
569     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
570 }
571
572 /*!
573  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
574  * cells each node belongs to.
575  * \warning For speed reasons, this method does not check if node ids in the nodal
576  *          connectivity correspond to the size of node coordinates array.
577  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
578  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
579  *        dividing cell ids in \a revNodal into groups each referring to one
580  *        node. Its every element (except the last one) is an index pointing to the
581  *         first id of a group of cells. For example cells sharing the node #1 are 
582  *        described by following range of indices: 
583  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
584  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
585  *        Number of cells sharing the *i*-th node is
586  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
587  * \throw If the coordinates array is not set.
588  * \throw If the nodal connectivity of cells is not defined.
589  * 
590  * \if ENABLE_EXAMPLES
591  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
592  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
593  * \endif
594  */
595 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
596 {
597   checkFullyDefined();
598   int nbOfNodes=getNumberOfNodes();
599   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
600   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
601   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
602   const int *conn=_nodal_connec->getConstPointer();
603   const int *connIndex=_nodal_connec_index->getConstPointer();
604   int nbOfCells=getNumberOfCells();
605   int nbOfEltsInRevNodal=0;
606   for(int eltId=0;eltId<nbOfCells;eltId++)
607     {
608       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
609       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
610       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
611         if(*iter>=0)//for polyhedrons
612           {
613             nbOfEltsInRevNodal++;
614             revNodalIndxPtr[(*iter)+1]++;
615           }
616     }
617   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
618   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
619   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
620   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
621   for(int eltId=0;eltId<nbOfCells;eltId++)
622     {
623       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
624       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
625       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
626         if(*iter>=0)//for polyhedrons
627           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
628     }
629 }
630
631 /// @cond INTERNAL
632
633 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
634 {
635   return id;
636 }
637
638 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
639 {
640   if(!compute)
641     return id+1;
642   else
643     {
644       if(cm.getOrientationStatus(nb,conn1,conn2))
645         return id+1;
646       else
647         return -(id+1);
648     }
649 }
650
651 class MinusOneSonsGenerator
652 {
653 public:
654   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
655   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
656   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
657   static const int DELTA=1;
658 private:
659   const INTERP_KERNEL::CellModel& _cm;
660 };
661
662 class MinusOneSonsGeneratorBiQuadratic
663 {
664 public:
665   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
666   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
667   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
668   static const int DELTA=1;
669 private:
670   const INTERP_KERNEL::CellModel& _cm;
671 };
672
673 class MinusTwoSonsGenerator
674 {
675 public:
676   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
677   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
678   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
679   static const int DELTA=2;
680 private:
681   const INTERP_KERNEL::CellModel& _cm;
682 };
683
684 /// @endcond
685
686 /*!
687  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
688  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
689  * describing correspondence between cells of \a this and the result meshes are
690  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
691  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
692  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
693  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
694  * \warning For speed reasons, this method does not check if node ids in the nodal
695  *          connectivity correspond to the size of node coordinates array.
696  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
697  *          to write this mesh to the MED file, its cells must be sorted using
698  *          sortCellsInMEDFileFrmt().
699  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
700  *         each cell of \a this mesh.
701  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
702  *        dividing cell ids in \a desc into groups each referring to one
703  *        cell of \a this mesh. Its every element (except the last one) is an index
704  *        pointing to the first id of a group of cells. For example cells of the
705  *        result mesh bounding the cell #1 of \a this mesh are described by following
706  *        range of indices:
707  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
708  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
709  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
710  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
711  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
712  *         by each cell of the result mesh.
713  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
714  *        in the result mesh,
715  *        dividing cell ids in \a revDesc into groups each referring to one
716  *        cell of the result mesh the same way as \a descIndx divides \a desc.
717  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
718  *        delete this mesh using decrRef() as it is no more needed.
719  *  \throw If the coordinates array is not set.
720  *  \throw If the nodal connectivity of cells is node defined.
721  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
722  *         revDescIndx == NULL.
723  * 
724  *  \if ENABLE_EXAMPLES
725  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
726  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
727  *  \endif
728  * \sa buildDescendingConnectivity2()
729  */
730 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
731 {
732   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
733 }
734
735 /*!
736  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
737  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
738  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
739  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
740  * \sa MEDCouplingUMesh::buildDescendingConnectivity
741  */
742 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
743 {
744   checkFullyDefined();
745   if(getMeshDimension()!=3)
746     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
747   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
748 }
749
750 /*!
751  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
752  * this->getMeshDimension(), that bound cells of \a this mesh. In
753  * addition arrays describing correspondence between cells of \a this and the result
754  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
755  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
756  *  mesh. This method differs from buildDescendingConnectivity() in that apart
757  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
758  * result meshes. So a positive id means that order of nodes in corresponding cells
759  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
760  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
761  * i.e. cell ids are one-based.
762  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
763  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
764  * \warning For speed reasons, this method does not check if node ids in the nodal
765  *          connectivity correspond to the size of node coordinates array.
766  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
767  *          to write this mesh to the MED file, its cells must be sorted using
768  *          sortCellsInMEDFileFrmt().
769  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
770  *         each cell of \a this mesh.
771  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
772  *        dividing cell ids in \a desc into groups each referring to one
773  *        cell of \a this mesh. Its every element (except the last one) is an index
774  *        pointing to the first id of a group of cells. For example cells of the
775  *        result mesh bounding the cell #1 of \a this mesh are described by following
776  *        range of indices:
777  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
778  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
779  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
780  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
781  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
782  *         by each cell of the result mesh.
783  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
784  *        in the result mesh,
785  *        dividing cell ids in \a revDesc into groups each referring to one
786  *        cell of the result mesh the same way as \a descIndx divides \a desc.
787  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
788  *        shares the node coordinates array with \a this mesh. The caller is to
789  *        delete this mesh using decrRef() as it is no more needed.
790  *  \throw If the coordinates array is not set.
791  *  \throw If the nodal connectivity of cells is node defined.
792  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
793  *         revDescIndx == NULL.
794  * 
795  *  \if ENABLE_EXAMPLES
796  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
797  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
798  *  \endif
799  * \sa buildDescendingConnectivity()
800  */
801 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
802 {
803   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
804 }
805
806 /*!
807  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
808  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
809  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
810  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
811  *
812  * \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
813  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
814  * \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.
815  */
816 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
817 {
818   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
819   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
822   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
823   meshDM1=0;
824   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
825 }
826
827 /*!
828  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
829  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
830  * excluding a set of meshdim-1 cells in input descending connectivity.
831  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
832  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
833  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
834  *
835  * \param [in] desc descending connectivity array.
836  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
837  * \param [in] revDesc reverse descending connectivity array.
838  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
839  * \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
840  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
841  * \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.
842  */
843 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
844                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
845 {
846   if(!desc || !descIndx || !revDesc || !revDescIndx)
847     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
848   const int *descPtr=desc->getConstPointer();
849   const int *descIPtr=descIndx->getConstPointer();
850   const int *revDescPtr=revDesc->getConstPointer();
851   const int *revDescIPtr=revDescIndx->getConstPointer();
852   //
853   int nbCells=descIndx->getNumberOfTuples()-1;
854   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
855   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
856   int *out1Ptr=out1->getPointer();
857   *out1Ptr++=0;
858   out0->reserve(desc->getNumberOfTuples());
859   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
860     {
861       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
862         {
863           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
864           s.erase(i);
865           out0->insertAtTheEnd(s.begin(),s.end());
866         }
867       *out1Ptr=out0->getNumberOfTuples();
868     }
869   neighbors=out0.retn();
870   neighborsIndx=out1.retn();
871 }
872
873 /*!
874  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
875  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
876  * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
877  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
878  *
879  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
880  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
881  * \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.
882  */
883 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
884 {
885   checkFullyDefined();
886   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
888   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
889   switch(mdim)
890   {
891     case 3:
892       {
893         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
894         break;
895       }
896     case 2:
897       {
898         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
899         break;
900       }
901     case 1:
902       {
903         mesh1D=const_cast<MEDCouplingUMesh *>(this);
904         mesh1D->incrRef();
905         break;
906       }
907     default:
908       {
909         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
910       }
911   }
912   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
913   mesh1D->getReverseNodalConnectivity(desc,descIndx);
914   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
915   ret0->alloc(desc->getNumberOfTuples(),1);
916   int *r0Pt(ret0->getPointer());
917   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
918   for(int i=0;i<nbNodes;i++,rni++)
919     {
920       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
921         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
922     }
923   neighbors=ret0.retn();
924   neighborsIdx=descIndx.retn();
925 }
926
927 /// @cond INTERNAL
928
929 /*!
930  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
931  * For speed reasons no check of this will be done.
932  */
933 template<class SonsGenerator>
934 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
935 {
936   if(!desc || !descIndx || !revDesc || !revDescIndx)
937     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
938   checkConnectivityFullyDefined();
939   int nbOfCells=getNumberOfCells();
940   int nbOfNodes=getNumberOfNodes();
941   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
942   int *revNodalIndxPtr=revNodalIndx->getPointer();
943   const int *conn=_nodal_connec->getConstPointer();
944   const int *connIndex=_nodal_connec_index->getConstPointer();
945   std::string name="Mesh constituent of "; name+=getName();
946   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
947   ret->setCoords(getCoords());
948   ret->allocateCells(2*nbOfCells);
949   descIndx->alloc(nbOfCells+1,1);
950   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
951   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
952   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
953     {
954       int pos=connIndex[eltId];
955       int posP1=connIndex[eltId+1];
956       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
957       SonsGenerator sg(cm);
958       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
959       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
960       for(unsigned i=0;i<nbOfSons;i++)
961         {
962           INTERP_KERNEL::NormalizedCellType cmsId;
963           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
964           for(unsigned k=0;k<nbOfNodesSon;k++)
965             if(tmp[k]>=0)
966               revNodalIndxPtr[tmp[k]+1]++;
967           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
968           revDesc2->pushBackSilent(eltId);
969         }
970       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
971     }
972   int nbOfCellsM1=ret->getNumberOfCells();
973   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
975   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
976   int *revNodalPtr=revNodal->getPointer();
977   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
978   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
979   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
980     {
981       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
982       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
983       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
984         if(*iter>=0)//for polyhedrons
985           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
986     }
987   //
988   DataArrayInt *commonCells=0,*commonCellsI=0;
989   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
990   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
991   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
992   int newNbOfCellsM1=-1;
993   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
994                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
995   std::vector<bool> isImpacted(nbOfCellsM1,false);
996   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
997     for(int work2=work[0];work2!=work[1];work2++)
998       isImpacted[commonCellsPtr[work2]]=true;
999   const int *o2nM1Ptr=o2nM1->getConstPointer();
1000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1001   const int *n2oM1Ptr=n2oM1->getConstPointer();
1002   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1003   ret2->copyTinyInfoFrom(this);
1004   desc->alloc(descIndx->back(),1);
1005   int *descPtr=desc->getPointer();
1006   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1007   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1008     {
1009       if(!isImpacted[i])
1010         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1011       else
1012         {
1013           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1014             {
1015               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1016               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1017             }
1018           else
1019             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1020         }
1021     }
1022   revDesc->reserve(newNbOfCellsM1);
1023   revDescIndx->alloc(newNbOfCellsM1+1,1);
1024   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1025   const int *revDesc2Ptr=revDesc2->getConstPointer();
1026   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1027     {
1028       int oldCellIdM1=n2oM1Ptr[i];
1029       if(!isImpacted[oldCellIdM1])
1030         {
1031           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1032           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1033         }
1034       else
1035         {
1036           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1037             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1038           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1039           commonCellsIPtr++;
1040         }
1041     }
1042   //
1043   return ret2.retn();
1044 }
1045
1046 struct MEDCouplingAccVisit
1047 {
1048   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1049   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1050   int _new_nb_of_nodes;
1051 };
1052
1053 /// @endcond
1054
1055 /*!
1056  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1057  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1058  * array of cell ids. Pay attention that after conversion all algorithms work slower
1059  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1060  * conversion due presence of invalid ids in the array of cells to convert, as a
1061  * result \a this mesh contains some already converted elements. In this case the 2D
1062  * mesh remains valid but 3D mesh becomes \b inconsistent!
1063  *  \warning This method can significantly modify the order of geometric types in \a this,
1064  *          hence, to write this mesh to the MED file, its cells must be sorted using
1065  *          sortCellsInMEDFileFrmt().
1066  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1067  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1068  *         cellIdsToConvertBg.
1069  *  \throw If the coordinates array is not set.
1070  *  \throw If the nodal connectivity of cells is node defined.
1071  *  \throw If dimension of \a this mesh is not either 2 or 3.
1072  *
1073  *  \if ENABLE_EXAMPLES
1074  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1075  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1076  *  \endif
1077  */
1078 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1079 {
1080   checkFullyDefined();
1081   int dim=getMeshDimension();
1082   if(dim<2 || dim>3)
1083     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1084   int nbOfCells(getNumberOfCells());
1085   if(dim==2)
1086     {
1087       const int *connIndex=_nodal_connec_index->getConstPointer();
1088       int *conn=_nodal_connec->getPointer();
1089       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1090         {
1091           if(*iter>=0 && *iter<nbOfCells)
1092             {
1093               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1094               if(!cm.isQuadratic())
1095                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1096               else
1097                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1098             }
1099           else
1100             {
1101               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1102               oss << " in range [0," << nbOfCells << ") !";
1103               throw INTERP_KERNEL::Exception(oss.str().c_str());
1104             }
1105         }
1106     }
1107   else
1108     {
1109       int *connIndex(_nodal_connec_index->getPointer());
1110       const int *connOld(_nodal_connec->getConstPointer());
1111       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1112       std::vector<bool> toBeDone(nbOfCells,false);
1113       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1114         {
1115           if(*iter>=0 && *iter<nbOfCells)
1116             toBeDone[*iter]=true;
1117           else
1118             {
1119               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1120               oss << " in range [0," << nbOfCells << ") !";
1121               throw INTERP_KERNEL::Exception(oss.str().c_str());
1122             }
1123         }
1124       for(int cellId=0;cellId<nbOfCells;cellId++)
1125         {
1126           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1127           int lgthOld(posP1-pos-1);
1128           if(toBeDone[cellId])
1129             {
1130               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1131               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1132               int *tmp(new int[nbOfFaces*lgthOld+1]);
1133               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1134               for(unsigned j=0;j<nbOfFaces;j++)
1135                 {
1136                   INTERP_KERNEL::NormalizedCellType type;
1137                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1138                   work+=offset;
1139                   *work++=-1;
1140                 }
1141               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1142               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1143               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1144               delete [] tmp;
1145             }
1146           else
1147             {
1148               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1149               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1150             }
1151         }
1152       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1153     }
1154   computeTypes();
1155 }
1156
1157 /*!
1158  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1159  * polyhedrons (if \a this is a 3D mesh).
1160  *  \warning As this method is purely for user-friendliness and no optimization is
1161  *          done to avoid construction of a useless vector, this method can be costly
1162  *          in memory.
1163  *  \throw If the coordinates array is not set.
1164  *  \throw If the nodal connectivity of cells is node defined.
1165  *  \throw If dimension of \a this mesh is not either 2 or 3.
1166  */
1167 void MEDCouplingUMesh::convertAllToPoly()
1168 {
1169   int nbOfCells=getNumberOfCells();
1170   std::vector<int> cellIds(nbOfCells);
1171   for(int i=0;i<nbOfCells;i++)
1172     cellIds[i]=i;
1173   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1174 }
1175
1176 /*!
1177  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1178  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1179  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1180  * base facet of the volume and the second half of nodes describes an opposite facet
1181  * having the same number of nodes as the base one. This method converts such
1182  * connectivity to a valid polyhedral format where connectivity of each facet is
1183  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1184  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1185  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1186  * a correct orientation of the first facet of a polyhedron, else orientation of a
1187  * corrected cell is reverse.<br>
1188  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1189  * it releases the user from boring description of polyhedra connectivity in the valid
1190  * format.
1191  *  \throw If \a this->getMeshDimension() != 3.
1192  *  \throw If \a this->getSpaceDimension() != 3.
1193  *  \throw If the nodal connectivity of cells is not defined.
1194  *  \throw If the coordinates array is not set.
1195  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1196  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1197  *
1198  *  \if ENABLE_EXAMPLES
1199  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1200  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1201  *  \endif
1202  */
1203 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1204 {
1205   checkFullyDefined();
1206   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1207     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1208   int nbOfCells=getNumberOfCells();
1209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1210   newCi->alloc(nbOfCells+1,1);
1211   int *newci=newCi->getPointer();
1212   const int *ci=_nodal_connec_index->getConstPointer();
1213   const int *c=_nodal_connec->getConstPointer();
1214   newci[0]=0;
1215   for(int i=0;i<nbOfCells;i++)
1216     {
1217       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1218       if(type==INTERP_KERNEL::NORM_POLYHED)
1219         {
1220           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1221             {
1222               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1223               throw INTERP_KERNEL::Exception(oss.str().c_str());
1224             }
1225           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1226           if(n2%2!=0)
1227             {
1228               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 !";
1229               throw INTERP_KERNEL::Exception(oss.str().c_str());
1230             }
1231           int n1=(int)(n2/2);
1232           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)
1233         }
1234       else
1235         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1236     }
1237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1238   newC->alloc(newci[nbOfCells],1);
1239   int *newc=newC->getPointer();
1240   for(int i=0;i<nbOfCells;i++)
1241     {
1242       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1243       if(type==INTERP_KERNEL::NORM_POLYHED)
1244         {
1245           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1246           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1247           *newc++=-1;
1248           for(std::size_t j=0;j<n1;j++)
1249             {
1250               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1251               newc[n1+5*j]=-1;
1252               newc[n1+5*j+1]=c[ci[i]+1+j];
1253               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1254               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1255               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1256             }
1257           newc+=n1*6;
1258         }
1259       else
1260         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1261     }
1262   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1263   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1264 }
1265
1266
1267 /*!
1268  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1269  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1270  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1271  *          to write this mesh to the MED file, its cells must be sorted using
1272  *          sortCellsInMEDFileFrmt().
1273  * \return \c true if at least one cell has been converted, \c false else. In the
1274  *         last case the nodal connectivity remains unchanged.
1275  * \throw If the coordinates array is not set.
1276  * \throw If the nodal connectivity of cells is not defined.
1277  * \throw If \a this->getMeshDimension() < 0.
1278  */
1279 bool MEDCouplingUMesh::unPolyze()
1280 {
1281   checkFullyDefined();
1282   int mdim=getMeshDimension();
1283   if(mdim<0)
1284     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1285   if(mdim<=1)
1286     return false;
1287   int nbOfCells=getNumberOfCells();
1288   if(nbOfCells<1)
1289     return false;
1290   int initMeshLgth=getMeshLength();
1291   int *conn=_nodal_connec->getPointer();
1292   int *index=_nodal_connec_index->getPointer();
1293   int posOfCurCell=0;
1294   int newPos=0;
1295   int lgthOfCurCell;
1296   bool ret=false;
1297   for(int i=0;i<nbOfCells;i++)
1298     {
1299       lgthOfCurCell=index[i+1]-posOfCurCell;
1300       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1301       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1302       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1303       int newLgth;
1304       if(cm.isDynamic())
1305         {
1306           switch(cm.getDimension())
1307           {
1308             case 2:
1309               {
1310                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1311                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1312                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1313                 break;
1314               }
1315             case 3:
1316               {
1317                 int nbOfFaces,lgthOfPolyhConn;
1318                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1319                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1320                 break;
1321               }
1322             case 1:
1323               {
1324                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1325                 break;
1326               }
1327           }
1328           ret=ret || (newType!=type);
1329           conn[newPos]=newType;
1330           newPos+=newLgth+1;
1331           posOfCurCell=index[i+1];
1332           index[i+1]=newPos;
1333         }
1334       else
1335         {
1336           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1337           newPos+=lgthOfCurCell;
1338           posOfCurCell+=lgthOfCurCell;
1339           index[i+1]=newPos;
1340         }
1341     }
1342   if(newPos!=initMeshLgth)
1343     _nodal_connec->reAlloc(newPos);
1344   if(ret)
1345     computeTypes();
1346   return ret;
1347 }
1348
1349 /*!
1350  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1351  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1352  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1353  *
1354  * \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 
1355  *             precision.
1356  */
1357 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1358 {
1359   checkFullyDefined();
1360   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1361     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1362   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1363   coords->recenterForMaxPrecision(eps);
1364   //
1365   int nbOfCells=getNumberOfCells();
1366   const int *conn=_nodal_connec->getConstPointer();
1367   const int *index=_nodal_connec_index->getConstPointer();
1368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1369   connINew->alloc(nbOfCells+1,1);
1370   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1371   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1372   bool changed=false;
1373   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1374     {
1375       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1376         {
1377           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1378           changed=true;
1379         }
1380       else
1381         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1382       *connINewPtr=connNew->getNumberOfTuples();
1383     }
1384   if(changed)
1385     setConnectivity(connNew,connINew,false);
1386 }
1387
1388 /*!
1389  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1390  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1391  * the format of returned DataArrayInt instance.
1392  * 
1393  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1394  * \sa MEDCouplingUMesh::getNodeIdsInUse
1395  */
1396 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1397 {
1398   checkConnectivityFullyDefined();
1399   int nbOfCells=getNumberOfCells();
1400   const int *connIndex=_nodal_connec_index->getConstPointer();
1401   const int *conn=_nodal_connec->getConstPointer();
1402   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1403   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1404   std::vector<bool> retS(maxElt,false);
1405   for(int i=0;i<nbOfCells;i++)
1406     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1407       if(conn[j]>=0)
1408         retS[conn[j]]=true;
1409   int sz=0;
1410   for(int i=0;i<maxElt;i++)
1411     if(retS[i])
1412       sz++;
1413   DataArrayInt *ret=DataArrayInt::New();
1414   ret->alloc(sz,1);
1415   int *retPtr=ret->getPointer();
1416   for(int i=0;i<maxElt;i++)
1417     if(retS[i])
1418       *retPtr++=i;
1419   return ret;
1420 }
1421
1422 /*!
1423  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1424  * \sa MEDCouplingUMesh::getNodeIdsInUse
1425  */
1426 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1427 {
1428   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1429   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1430   for(int i=0;i<nbOfCells;i++)
1431     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1432       if(conn[j]>=0)
1433         {
1434           if(conn[j]<nbOfNodes)
1435             nodeIdsInUse[conn[j]]=true;
1436           else
1437             {
1438               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1439               throw INTERP_KERNEL::Exception(oss.str().c_str());
1440             }
1441         }
1442 }
1443
1444 /*!
1445  * Finds nodes not used in any cell and returns an array giving a new id to every node
1446  * by excluding the unused nodes, for which the array holds -1. The result array is
1447  * a mapping in "Old to New" mode. 
1448  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1449  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1450  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1451  *          if the node is unused or a new id else. The caller is to delete this
1452  *          array using decrRef() as it is no more needed.  
1453  *  \throw If the coordinates array is not set.
1454  *  \throw If the nodal connectivity of cells is not defined.
1455  *  \throw If the nodal connectivity includes an invalid id.
1456  *
1457  *  \if ENABLE_EXAMPLES
1458  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1459  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1460  *  \endif
1461  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1462  */
1463 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1464 {
1465   nbrOfNodesInUse=-1;
1466   int nbOfNodes(getNumberOfNodes());
1467   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1468   ret->alloc(nbOfNodes,1);
1469   int *traducer=ret->getPointer();
1470   std::fill(traducer,traducer+nbOfNodes,-1);
1471   int nbOfCells=getNumberOfCells();
1472   const int *connIndex=_nodal_connec_index->getConstPointer();
1473   const int *conn=_nodal_connec->getConstPointer();
1474   for(int i=0;i<nbOfCells;i++)
1475     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1476       if(conn[j]>=0)
1477         {
1478           if(conn[j]<nbOfNodes)
1479             traducer[conn[j]]=1;
1480           else
1481             {
1482               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1483               throw INTERP_KERNEL::Exception(oss.str().c_str());
1484             }
1485         }
1486   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1487   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1488   return ret.retn();
1489 }
1490
1491 /*!
1492  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1493  * For each cell in \b this the number of nodes constituting cell is computed.
1494  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1495  * So for pohyhedrons some nodes can be counted several times in the returned result.
1496  * 
1497  * \return a newly allocated array
1498  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1499  */
1500 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1501 {
1502   checkConnectivityFullyDefined();
1503   int nbOfCells=getNumberOfCells();
1504   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1505   ret->alloc(nbOfCells,1);
1506   int *retPtr=ret->getPointer();
1507   const int *conn=getNodalConnectivity()->getConstPointer();
1508   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1509   for(int i=0;i<nbOfCells;i++,retPtr++)
1510     {
1511       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1512         *retPtr=connI[i+1]-connI[i]-1;
1513       else
1514         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1515     }
1516   return ret.retn();
1517 }
1518
1519 /*!
1520  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1521  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1522  *
1523  * \return DataArrayInt * - new object to be deallocated by the caller.
1524  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1525  */
1526 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1527 {
1528   checkConnectivityFullyDefined();
1529   int nbOfCells=getNumberOfCells();
1530   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1531   ret->alloc(nbOfCells,1);
1532   int *retPtr=ret->getPointer();
1533   const int *conn=getNodalConnectivity()->getConstPointer();
1534   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1535   for(int i=0;i<nbOfCells;i++,retPtr++)
1536     {
1537       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1538       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1539         *retPtr=(int)s.size();
1540       else
1541         {
1542           s.erase(-1);
1543           *retPtr=(int)s.size();
1544         }
1545     }
1546   return ret.retn();
1547 }
1548
1549 /*!
1550  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1551  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1552  * 
1553  * \return a newly allocated array
1554  */
1555 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1556 {
1557   checkConnectivityFullyDefined();
1558   int nbOfCells=getNumberOfCells();
1559   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1560   ret->alloc(nbOfCells,1);
1561   int *retPtr=ret->getPointer();
1562   const int *conn=getNodalConnectivity()->getConstPointer();
1563   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1564   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1565     {
1566       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1567       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1568     }
1569   return ret.retn();
1570 }
1571
1572 /*!
1573  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1574  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1575  * array mean that the corresponding old node is no more used. 
1576  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1577  *           this->getNumberOfNodes() before call of this method. The caller is to
1578  *           delete this array using decrRef() as it is no more needed. 
1579  *  \throw If the coordinates array is not set.
1580  *  \throw If the nodal connectivity of cells is not defined.
1581  *  \throw If the nodal connectivity includes an invalid id.
1582  *
1583  *  \if ENABLE_EXAMPLES
1584  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1585  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1586  *  \endif
1587  */
1588 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1589 {
1590   return MEDCouplingPointSet::zipCoordsTraducer();
1591 }
1592
1593 /*!
1594  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1595  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1596  */
1597 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1598 {
1599   switch(compType)
1600   {
1601     case 0:
1602       return AreCellsEqual0(conn,connI,cell1,cell2);
1603     case 1:
1604       return AreCellsEqual1(conn,connI,cell1,cell2);
1605     case 2:
1606       return AreCellsEqual2(conn,connI,cell1,cell2);
1607     case 3:
1608       return AreCellsEqual3(conn,connI,cell1,cell2);
1609     case 7:
1610       return AreCellsEqual7(conn,connI,cell1,cell2);
1611   }
1612   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1613 }
1614
1615 /*!
1616  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1617  */
1618 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1619 {
1620   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1621     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1622   return 0;
1623 }
1624
1625 /*!
1626  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1627  */
1628 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1629 {
1630   int sz=connI[cell1+1]-connI[cell1];
1631   if(sz==connI[cell2+1]-connI[cell2])
1632     {
1633       if(conn[connI[cell1]]==conn[connI[cell2]])
1634         {
1635           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1636           unsigned dim=cm.getDimension();
1637           if(dim!=3)
1638             {
1639               if(dim!=1)
1640                 {
1641                   int sz1=2*(sz-1);
1642                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1643                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1644                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1645                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1646                   return work!=tmp+sz1?1:0;
1647                 }
1648               else
1649                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1650             }
1651           else
1652             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1653         }
1654     }
1655   return 0;
1656 }
1657
1658 /*!
1659  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1660  */
1661 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1662 {
1663   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1664     {
1665       if(conn[connI[cell1]]==conn[connI[cell2]])
1666         {
1667           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1668           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1669           return s1==s2?1:0;
1670         }
1671     }
1672   return 0;
1673 }
1674
1675 /*!
1676  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1677  */
1678 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1679 {
1680   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1681     {
1682       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1683       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1684       return s1==s2?1:0;
1685     }
1686   return 0;
1687 }
1688
1689 /*!
1690  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1691  */
1692 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1693 {
1694   int sz=connI[cell1+1]-connI[cell1];
1695   if(sz==connI[cell2+1]-connI[cell2])
1696     {
1697       if(conn[connI[cell1]]==conn[connI[cell2]])
1698         {
1699           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1700           unsigned dim=cm.getDimension();
1701           if(dim!=3)
1702             {
1703               if(dim!=1)
1704                 {
1705                   int sz1=2*(sz-1);
1706                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1707                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1708                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1709                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1710                   if(work!=tmp+sz1)
1711                     return 1;
1712                   else
1713                     {
1714                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1715                       std::reverse_iterator<int *> it2((int *)tmp);
1716                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1717                         return 2;
1718                       else
1719                         return 0;
1720                     }
1721
1722                   return work!=tmp+sz1?1:0;
1723                 }
1724               else
1725                 {//case of SEG2 and SEG3
1726                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1727                     return 1;
1728                   if(!cm.isQuadratic())
1729                     {
1730                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1731                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1732                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1733                         return 2;
1734                       return 0;
1735                     }
1736                   else
1737                     {
1738                       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])
1739                         return 2;
1740                       return 0;
1741                     }
1742                 }
1743             }
1744           else
1745             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1746         }
1747     }
1748   return 0;
1749 }
1750
1751 /*!
1752  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1753  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1754  * and result remains unchanged.
1755  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1756  * If in 'candidates' pool -1 value is considered as an empty value.
1757  * WARNING this method returns only ONE set of result !
1758  */
1759 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1760 {
1761   if(candidates.size()<1)
1762     return false;
1763   bool ret=false;
1764   std::vector<int>::const_iterator iter=candidates.begin();
1765   int start=(*iter++);
1766   for(;iter!=candidates.end();iter++)
1767     {
1768       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1769       if(status!=0)
1770         {
1771           if(!ret)
1772             {
1773               result->pushBackSilent(start);
1774               ret=true;
1775             }
1776           if(status==1)
1777             result->pushBackSilent(*iter);
1778           else
1779             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1780         }
1781     }
1782   return ret;
1783 }
1784
1785 /*!
1786  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1787  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1788  *
1789  * \param [in] compType input specifying the technique used to compare cells each other.
1790  *   - 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.
1791  *   - 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)
1792  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1793  *   - 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
1794  * can be used for users not sensitive to orientation of cell
1795  * \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.
1796  * \param [out] commonCells
1797  * \param [out] commonCellsI
1798  * \return the correspondance array old to new in a newly allocated array.
1799  * 
1800  */
1801 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1802 {
1803   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1804   getReverseNodalConnectivity(revNodal,revNodalI);
1805   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1806 }
1807
1808 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1809                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1810 {
1811   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1812   int nbOfCells=nodalI->getNumberOfTuples()-1;
1813   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1814   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1815   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1816   std::vector<bool> isFetched(nbOfCells,false);
1817   if(startCellId==0)
1818     {
1819       for(int i=0;i<nbOfCells;i++)
1820         {
1821           if(!isFetched[i])
1822             {
1823               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1824               std::vector<int> v,v2;
1825               if(connOfNode!=connPtr+connIPtr[i+1])
1826                 {
1827                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1828                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1829                   connOfNode++;
1830                 }
1831               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1832                 if(*connOfNode>=0)
1833                   {
1834                     v=v2;
1835                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1836                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1837                     v2.resize(std::distance(v2.begin(),it));
1838                   }
1839               if(v2.size()>1)
1840                 {
1841                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1842                     {
1843                       int pos=commonCellsI->back();
1844                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1845                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1846                         isFetched[*it]=true;
1847                     }
1848                 }
1849             }
1850         }
1851     }
1852   else
1853     {
1854       for(int i=startCellId;i<nbOfCells;i++)
1855         {
1856           if(!isFetched[i])
1857             {
1858               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1859               std::vector<int> v,v2;
1860               if(connOfNode!=connPtr+connIPtr[i+1])
1861                 {
1862                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1863                   connOfNode++;
1864                 }
1865               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1866                 if(*connOfNode>=0)
1867                   {
1868                     v=v2;
1869                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1870                     v2.resize(std::distance(v2.begin(),it));
1871                   }
1872               if(v2.size()>1)
1873                 {
1874                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1875                     {
1876                       int pos=commonCellsI->back();
1877                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1878                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1879                         isFetched[*it]=true;
1880                     }
1881                 }
1882             }
1883         }
1884     }
1885   commonCellsArr=commonCells.retn();
1886   commonCellsIArr=commonCellsI.retn();
1887 }
1888
1889 /*!
1890  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1891  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1892  * than \a other->getNumberOfCells() in the returned array means that there is no
1893  * corresponding cell in \a this mesh.
1894  * It is expected that \a this and \a other meshes share the same node coordinates
1895  * array, if it is not so an exception is thrown. 
1896  *  \param [in] other - the mesh to compare with.
1897  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1898  *         valid values [0,1,2], see zipConnectivityTraducer().
1899  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1900  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1901  *         values. The caller is to delete this array using
1902  *         decrRef() as it is no more needed.
1903  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1904  *         mesh.
1905  *
1906  *  \if ENABLE_EXAMPLES
1907  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1908  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1909  *  \endif
1910  *  \sa checkDeepEquivalOnSameNodesWith()
1911  *  \sa checkGeoEquivalWith()
1912  */
1913 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1914 {
1915   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1916   int nbOfCells=getNumberOfCells();
1917   static const int possibleCompType[]={0,1,2};
1918   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1919     {
1920       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1921       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1922       oss << " !";
1923       throw INTERP_KERNEL::Exception(oss.str().c_str());
1924     }
1925   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1926   arr=o2n->substr(nbOfCells);
1927   arr->setName(other->getName());
1928   int tmp;
1929   if(other->getNumberOfCells()==0)
1930     return true;
1931   return arr->getMaxValue(tmp)<nbOfCells;
1932 }
1933
1934 /*!
1935  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1936  * This method tries to determine if \b other is fully included in \b this.
1937  * The main difference is that this method is not expected to throw exception.
1938  * This method has two outputs :
1939  *
1940  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1941  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1942  */
1943 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1944 {
1945   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1946   DataArrayInt *commonCells=0,*commonCellsI=0;
1947   int thisNbCells=getNumberOfCells();
1948   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1949   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1950   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1951   int otherNbCells=other->getNumberOfCells();
1952   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1953   arr2->alloc(otherNbCells,1);
1954   arr2->fillWithZero();
1955   int *arr2Ptr=arr2->getPointer();
1956   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1957   for(int i=0;i<nbOfCommon;i++)
1958     {
1959       int start=commonCellsPtr[commonCellsIPtr[i]];
1960       if(start<thisNbCells)
1961         {
1962           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1963             {
1964               int sig=commonCellsPtr[j]>0?1:-1;
1965               int val=std::abs(commonCellsPtr[j])-1;
1966               if(val>=thisNbCells)
1967                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1968             }
1969         }
1970     }
1971   arr2->setName(other->getName());
1972   if(arr2->presenceOfValue(0))
1973     return false;
1974   arr=arr2.retn();
1975   return true;
1976 }
1977
1978 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1979 {
1980   if(!other)
1981     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1982   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1983   if(!otherC)
1984     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1985   std::vector<const MEDCouplingUMesh *> ms(2);
1986   ms[0]=this;
1987   ms[1]=otherC;
1988   return MergeUMeshesOnSameCoords(ms);
1989 }
1990
1991 /*!
1992  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1993  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1994  * cellIds is not given explicitely but by a range python like.
1995  * 
1996  * \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.
1997  * \return a newly allocated
1998  * 
1999  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2000  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2001  */
2002 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2003 {
2004   if(getMeshDimension()!=-1)
2005     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2006   else
2007     {
2008       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2009       if(newNbOfCells!=1)
2010         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2011       if(start!=0)
2012         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2013       incrRef();
2014       return const_cast<MEDCouplingUMesh *>(this);
2015     }
2016 }
2017
2018 /*!
2019  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2020  * The result mesh shares or not the node coordinates array with \a this mesh depending
2021  * on \a keepCoords parameter.
2022  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2023  *           to write this mesh to the MED file, its cells must be sorted using
2024  *           sortCellsInMEDFileFrmt().
2025  *  \param [in] begin - an array of cell ids to include to the new mesh.
2026  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2027  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2028  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2029  *         by calling zipCoords().
2030  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2031  *         to delete this mesh using decrRef() as it is no more needed. 
2032  *  \throw If the coordinates array is not set.
2033  *  \throw If the nodal connectivity of cells is not defined.
2034  *  \throw If any cell id in the array \a begin is not valid.
2035  *
2036  *  \if ENABLE_EXAMPLES
2037  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2038  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2039  *  \endif
2040  */
2041 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2042 {
2043   if(getMeshDimension()!=-1)
2044     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2045   else
2046     {
2047       if(end-begin!=1)
2048         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2049       if(begin[0]!=0)
2050         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2051       incrRef();
2052       return const_cast<MEDCouplingUMesh *>(this);
2053     }
2054 }
2055
2056 /*!
2057  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2058  *
2059  * 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.
2060  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2061  * The number of cells of \b this will remain the same with this method.
2062  *
2063  * \param [in] begin begin of cell ids (included) of cells in this to assign
2064  * \param [in] end end of cell ids (excluded) of cells in this to assign
2065  * \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 ).
2066  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2067  */
2068 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2069 {
2070   checkConnectivityFullyDefined();
2071   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2072   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2073     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2074   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2075     {
2076       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2077       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2078       throw INTERP_KERNEL::Exception(oss.str().c_str());
2079     }
2080   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2081   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2082     {
2083       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2084       throw INTERP_KERNEL::Exception(oss.str().c_str());
2085     }
2086   int nbOfCells=getNumberOfCells();
2087   bool easyAssign=true;
2088   const int *connI=_nodal_connec_index->getConstPointer();
2089   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2090   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2091     {
2092       if(*it>=0 && *it<nbOfCells)
2093         {
2094           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2095         }
2096       else
2097         {
2098           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2099           throw INTERP_KERNEL::Exception(oss.str().c_str());
2100         }
2101     }
2102   if(easyAssign)
2103     {
2104       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2105       computeTypes();
2106     }
2107   else
2108     {
2109       DataArrayInt *arrOut=0,*arrIOut=0;
2110       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2111                                                arrOut,arrIOut);
2112       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2113       setConnectivity(arrOut,arrIOut,true);
2114     }
2115 }
2116
2117 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2118 {
2119   checkConnectivityFullyDefined();
2120   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2121   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2122     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2123   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2124     {
2125       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2126       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2127       throw INTERP_KERNEL::Exception(oss.str().c_str());
2128     }
2129   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2130   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2131     {
2132       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2133       throw INTERP_KERNEL::Exception(oss.str().c_str());
2134     }
2135   int nbOfCells=getNumberOfCells();
2136   bool easyAssign=true;
2137   const int *connI=_nodal_connec_index->getConstPointer();
2138   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2139   int it=start;
2140   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2141     {
2142       if(it>=0 && it<nbOfCells)
2143         {
2144           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2145         }
2146       else
2147         {
2148           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2149           throw INTERP_KERNEL::Exception(oss.str().c_str());
2150         }
2151     }
2152   if(easyAssign)
2153     {
2154       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2155       computeTypes();
2156     }
2157   else
2158     {
2159       DataArrayInt *arrOut=0,*arrIOut=0;
2160       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2161                                                 arrOut,arrIOut);
2162       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2163       setConnectivity(arrOut,arrIOut,true);
2164     }
2165 }                      
2166
2167 /*!
2168  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2169  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2170  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2171  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2172  *
2173  * \param [in] begin input start of array of node ids.
2174  * \param [in] end input end of array of node ids.
2175  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2176  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2177  */
2178 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2179 {
2180   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2181   checkConnectivityFullyDefined();
2182   int tmp=-1;
2183   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2184   std::vector<bool> fastFinder(sz,false);
2185   for(const int *work=begin;work!=end;work++)
2186     if(*work>=0 && *work<sz)
2187       fastFinder[*work]=true;
2188   int nbOfCells=getNumberOfCells();
2189   const int *conn=getNodalConnectivity()->getConstPointer();
2190   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2191   for(int i=0;i<nbOfCells;i++)
2192     {
2193       int ref=0,nbOfHit=0;
2194       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2195         if(*work2>=0)
2196           {
2197             ref++;
2198             if(fastFinder[*work2])
2199               nbOfHit++;
2200           }
2201       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2202         cellIdsKept->pushBackSilent(i);
2203     }
2204   cellIdsKeptArr=cellIdsKept.retn();
2205 }
2206
2207 /*!
2208  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2209  * this->getMeshDimension(), that bound some cells of \a this mesh.
2210  * The cells of lower dimension to include to the result mesh are selected basing on
2211  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2212  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2213  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2214  * created mesh shares the node coordinates array with \a this mesh. 
2215  *  \param [in] begin - the array of node ids.
2216  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2217  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2218  *         array \a begin are added, else cells whose any node is in the
2219  *         array \a begin are added.
2220  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2221  *         to delete this mesh using decrRef() as it is no more needed. 
2222  *  \throw If the coordinates array is not set.
2223  *  \throw If the nodal connectivity of cells is not defined.
2224  *  \throw If any node id in \a begin is not valid.
2225  *
2226  *  \if ENABLE_EXAMPLES
2227  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2228  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2229  *  \endif
2230  */
2231 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2232 {
2233   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2234   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2235   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2236   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2237   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2238 }
2239
2240 /*!
2241  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2242  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2243  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2244  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2245  *         by calling zipCoords().
2246  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2247  *         to delete this mesh using decrRef() as it is no more needed. 
2248  *  \throw If the coordinates array is not set.
2249  *  \throw If the nodal connectivity of cells is not defined.
2250  *
2251  *  \if ENABLE_EXAMPLES
2252  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2253  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2254  *  \endif
2255  */
2256 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2257 {
2258   DataArrayInt *desc=DataArrayInt::New();
2259   DataArrayInt *descIndx=DataArrayInt::New();
2260   DataArrayInt *revDesc=DataArrayInt::New();
2261   DataArrayInt *revDescIndx=DataArrayInt::New();
2262   //
2263   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2264   revDesc->decrRef();
2265   desc->decrRef();
2266   descIndx->decrRef();
2267   int nbOfCells=meshDM1->getNumberOfCells();
2268   const int *revDescIndxC=revDescIndx->getConstPointer();
2269   std::vector<int> boundaryCells;
2270   for(int i=0;i<nbOfCells;i++)
2271     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2272       boundaryCells.push_back(i);
2273   revDescIndx->decrRef();
2274   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2275   return ret;
2276 }
2277
2278 /*!
2279  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2280  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2281  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2282  */
2283 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2284 {
2285   checkFullyDefined();
2286   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2287   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2288   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2290   //
2291   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2292   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2293   //
2294   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2295   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2296   const int *revDescPtr=revDesc->getConstPointer();
2297   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2298   int nbOfCells=getNumberOfCells();
2299   std::vector<bool> ret1(nbOfCells,false);
2300   int sz=0;
2301   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2302     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2303       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2304   //
2305   DataArrayInt *ret2=DataArrayInt::New();
2306   ret2->alloc(sz,1);
2307   int *ret2Ptr=ret2->getPointer();
2308   sz=0;
2309   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2310     if(*it)
2311       *ret2Ptr++=sz;
2312   ret2->setName("BoundaryCells");
2313   return ret2;
2314 }
2315
2316 /*!
2317  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2318  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2319  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2320  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2321  *
2322  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2323  * This method method returns cells ids set s = s1 + s2 where :
2324  * 
2325  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2326  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2327  *
2328  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2329  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2330  *
2331  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2332  * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2333  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2334  */
2335 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2336 {
2337   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2338     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2339   checkConnectivityFullyDefined();
2340   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2341   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2342     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2345   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2347   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2348   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2349   DataArrayInt *idsOtherInConsti=0;
2350   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2351   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2352   if(!b)
2353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2354   std::set<int> s1;
2355   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2356     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2357   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2359   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2360   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2362   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2363   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2364   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2365   neighThisPartAuto=0;
2366   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2367   const int li[2]={0,1};
2368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2369   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2371   s_renum1->sort();
2372   //
2373   cellIdsRk0=s0arr.retn();
2374   cellIdsRk1=s_renum1.retn();
2375 }
2376
2377 /*!
2378  * 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
2379  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2380  * 
2381  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2382  */
2383 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2384 {
2385   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2386   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2387   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2389   //
2390   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2391   revDesc=0; desc=0; descIndx=0;
2392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2393   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2394   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2395 }
2396
2397 /*!
2398  * Finds nodes lying on the boundary of \a this mesh.
2399  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2400  *          nodes. The caller is to delete this array using decrRef() as it is no
2401  *          more needed.
2402  *  \throw If the coordinates array is not set.
2403  *  \throw If the nodal connectivity of cells is node defined.
2404  *
2405  *  \if ENABLE_EXAMPLES
2406  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2407  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2408  *  \endif
2409  */
2410 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2411 {
2412   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2413   return skin->computeFetchedNodeIds();
2414 }
2415
2416 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2417 {
2418   incrRef();
2419   return const_cast<MEDCouplingUMesh *>(this);
2420 }
2421
2422 /*!
2423  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2424  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2425  * 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.
2426  * 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.
2427  * 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.
2428  *
2429  * \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
2430  *             parameter is altered during the call.
2431  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2432  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2433  * \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.
2434  *
2435  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2436  */
2437 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2438                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2439 {
2440   checkFullyDefined();
2441   otherDimM1OnSameCoords.checkFullyDefined();
2442   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2443     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2444   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2445     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2446   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2447   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2448   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2449   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2450   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2451   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2452   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2453   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2454   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2455   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2456   //
2457   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2459   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2460   DataArrayInt *idsTmp=0;
2461   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2463   if(!b)
2464     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2465   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2466   DataArrayInt *tmp0=0,*tmp1=0;
2467   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2468   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2469   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2472   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2473   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2474   //
2475   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2476   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2477   nodeIdsToDuplicate=s3.retn();
2478 }
2479
2480 /*!
2481  * This method operates a modification of the connectivity and coords in \b this.
2482  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2483  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2484  * 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
2485  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2486  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2487  * 
2488  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2489  * 
2490  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2491  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2492  */
2493 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2494 {
2495   int nbOfNodes=getNumberOfNodes();
2496   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2497   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2498 }
2499
2500 /*!
2501  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2502  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2503  *
2504  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2505  *
2506  * \sa renumberNodesInConn
2507  */
2508 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2509 {
2510   checkConnectivityFullyDefined();
2511   int *conn(getNodalConnectivity()->getPointer());
2512   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2513   int nbOfCells(getNumberOfCells());
2514   for(int i=0;i<nbOfCells;i++)
2515     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2516       {
2517         int& node=conn[iconn];
2518         if(node>=0)//avoid polyhedron separator
2519           {
2520             node+=offset;
2521           }
2522       }
2523   _nodal_connec->declareAsNew();
2524   updateTime();
2525 }
2526
2527 /*!
2528  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2529  *  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
2530  *  of a big mesh.
2531  */
2532 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2533 {
2534   checkConnectivityFullyDefined();
2535   int *conn(getNodalConnectivity()->getPointer());
2536   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2537   int nbOfCells(getNumberOfCells());
2538   for(int i=0;i<nbOfCells;i++)
2539     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2540       {
2541         int& node=conn[iconn];
2542         if(node>=0)//avoid polyhedron separator
2543           {
2544             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2545             if(it!=newNodeNumbersO2N.end())
2546               {
2547                 node=(*it).second;
2548               }
2549             else
2550               {
2551                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2552                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2553               }
2554           }
2555       }
2556   _nodal_connec->declareAsNew();
2557   updateTime();
2558 }
2559
2560 /*!
2561  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2562  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2563  * This method is a generalization of shiftNodeNumbersInConn().
2564  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2565  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2566  *         this->getNumberOfNodes(), in "Old to New" mode. 
2567  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2568  *  \throw If the nodal connectivity of cells is not defined.
2569  *
2570  *  \if ENABLE_EXAMPLES
2571  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2572  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2573  *  \endif
2574  */
2575 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2576 {
2577   checkConnectivityFullyDefined();
2578   int *conn=getNodalConnectivity()->getPointer();
2579   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2580   int nbOfCells(getNumberOfCells());
2581   for(int i=0;i<nbOfCells;i++)
2582     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2583       {
2584         int& node=conn[iconn];
2585         if(node>=0)//avoid polyhedron separator
2586           {
2587             node=newNodeNumbersO2N[node];
2588           }
2589       }
2590   _nodal_connec->declareAsNew();
2591   updateTime();
2592 }
2593
2594 /*!
2595  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2596  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2597  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2598  * 
2599  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2600  */
2601 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2602 {
2603   checkConnectivityFullyDefined();
2604   int *conn=getNodalConnectivity()->getPointer();
2605   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2606   int nbOfCells=getNumberOfCells();
2607   for(int i=0;i<nbOfCells;i++)
2608     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2609       {
2610         int& node=conn[iconn];
2611         if(node>=0)//avoid polyhedron separator
2612           {
2613             node+=delta;
2614           }
2615       }
2616   _nodal_connec->declareAsNew();
2617   updateTime();
2618 }
2619
2620 /*!
2621  * This method operates a modification of the connectivity in \b this.
2622  * 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.
2623  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2624  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2625  * 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
2626  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2627  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2628  * 
2629  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2630  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2631  * 
2632  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2633  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2634  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2635  */
2636 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2637 {
2638   checkConnectivityFullyDefined();
2639   std::map<int,int> m;
2640   int val=offset;
2641   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2642     m[*work]=val;
2643   int *conn=getNodalConnectivity()->getPointer();
2644   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2645   int nbOfCells=getNumberOfCells();
2646   for(int i=0;i<nbOfCells;i++)
2647     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2648       {
2649         int& node=conn[iconn];
2650         if(node>=0)//avoid polyhedron separator
2651           {
2652             std::map<int,int>::iterator it=m.find(node);
2653             if(it!=m.end())
2654               node=(*it).second;
2655           }
2656       }
2657   updateTime();
2658 }
2659
2660 /*!
2661  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2662  *
2663  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2664  * After the call of this method the number of cells remains the same as before.
2665  *
2666  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2667  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2668  * be strictly in [0;this->getNumberOfCells()).
2669  *
2670  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2671  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2672  * should be contained in[0;this->getNumberOfCells()).
2673  * 
2674  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2675  */
2676 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2677 {
2678   checkConnectivityFullyDefined();
2679   int nbCells=getNumberOfCells();
2680   const int *array=old2NewBg;
2681   if(check)
2682     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2683   //
2684   const int *conn=_nodal_connec->getConstPointer();
2685   const int *connI=_nodal_connec_index->getConstPointer();
2686   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2687   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2688   const int *n2oPtr=n2o->begin();
2689   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2690   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2691   newConn->copyStringInfoFrom(*_nodal_connec);
2692   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2693   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2694   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2695   //
2696   int *newC=newConn->getPointer();
2697   int *newCI=newConnI->getPointer();
2698   int loc=0;
2699   newCI[0]=loc;
2700   for(int i=0;i<nbCells;i++)
2701     {
2702       int pos=n2oPtr[i];
2703       int nbOfElts=connI[pos+1]-connI[pos];
2704       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2705       loc+=nbOfElts;
2706       newCI[i+1]=loc;
2707     }
2708   //
2709   setConnectivity(newConn,newConnI);
2710   if(check)
2711     free(const_cast<int *>(array));
2712 }
2713
2714 /*!
2715  * Finds cells whose bounding boxes intersect a given bounding box.
2716  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2717  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2718  *         zMax (if in 3D). 
2719  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2720  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2721  *         extent of the bounding box of cell to produce an addition to this bounding box.
2722  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2723  *         cells. The caller is to delete this array using decrRef() as it is no more
2724  *         needed. 
2725  *  \throw If the coordinates array is not set.
2726  *  \throw If the nodal connectivity of cells is not defined.
2727  *
2728  *  \if ENABLE_EXAMPLES
2729  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2730  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2731  *  \endif
2732  */
2733 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2734 {
2735   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2736   if(getMeshDimension()==-1)
2737     {
2738       elems->pushBackSilent(0);
2739       return elems.retn();
2740     }
2741   int dim=getSpaceDimension();
2742   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2743   const int* conn      = getNodalConnectivity()->getConstPointer();
2744   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2745   const double* coords = getCoords()->getConstPointer();
2746   int nbOfCells=getNumberOfCells();
2747   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2748     {
2749       for (int i=0; i<dim; i++)
2750         {
2751           elem_bb[i*2]=std::numeric_limits<double>::max();
2752           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2753         }
2754
2755       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2756         {
2757           int node= conn[inode];
2758           if(node>=0)//avoid polyhedron separator
2759             {
2760               for (int idim=0; idim<dim; idim++)
2761                 {
2762                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2763                     {
2764                       elem_bb[idim*2] = coords[node*dim+idim] ;
2765                     }
2766                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2767                     {
2768                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2769                     }
2770                 }
2771             }
2772         }
2773       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2774         elems->pushBackSilent(ielem);
2775     }
2776   return elems.retn();
2777 }
2778
2779 /*!
2780  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2781  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2782  * added in 'elems' parameter.
2783  */
2784 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2785 {
2786   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2787   if(getMeshDimension()==-1)
2788     {
2789       elems->pushBackSilent(0);
2790       return elems.retn();
2791     }
2792   int dim=getSpaceDimension();
2793   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2794   const int* conn      = getNodalConnectivity()->getConstPointer();
2795   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2796   const double* coords = getCoords()->getConstPointer();
2797   int nbOfCells=getNumberOfCells();
2798   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2799     {
2800       for (int i=0; i<dim; i++)
2801         {
2802           elem_bb[i*2]=std::numeric_limits<double>::max();
2803           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2804         }
2805
2806       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2807         {
2808           int node= conn[inode];
2809           if(node>=0)//avoid polyhedron separator
2810             {
2811               for (int idim=0; idim<dim; idim++)
2812                 {
2813                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2814                     {
2815                       elem_bb[idim*2] = coords[node*dim+idim] ;
2816                     }
2817                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2818                     {
2819                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2820                     }
2821                 }
2822             }
2823         }
2824       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2825         elems->pushBackSilent(ielem);
2826     }
2827   return elems.retn();
2828 }
2829
2830 /*!
2831  * Returns a type of a cell by its id.
2832  *  \param [in] cellId - the id of the cell of interest.
2833  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2834  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2835  */
2836 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2837 {
2838   const int *ptI=_nodal_connec_index->getConstPointer();
2839   const int *pt=_nodal_connec->getConstPointer();
2840   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2841     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2842   else
2843     {
2844       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2845       throw INTERP_KERNEL::Exception(oss.str().c_str());
2846     }
2847 }
2848
2849 /*!
2850  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2851  * This method does not throw exception if geometric type \a type is not in \a this.
2852  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2853  * The coordinates array is not considered here.
2854  *
2855  * \param [in] type the geometric type
2856  * \return cell ids in this having geometric type \a type.
2857  */
2858 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2859 {
2860
2861   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2862   ret->alloc(0,1);
2863   checkConnectivityFullyDefined();
2864   int nbCells=getNumberOfCells();
2865   int mdim=getMeshDimension();
2866   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2867   if(mdim!=(int)cm.getDimension())
2868     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2869   const int *ptI=_nodal_connec_index->getConstPointer();
2870   const int *pt=_nodal_connec->getConstPointer();
2871   for(int i=0;i<nbCells;i++)
2872     {
2873       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2874         ret->pushBackSilent(i);
2875     }
2876   return ret.retn();
2877 }
2878
2879 /*!
2880  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2881  */
2882 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2883 {
2884   const int *ptI=_nodal_connec_index->getConstPointer();
2885   const int *pt=_nodal_connec->getConstPointer();
2886   int nbOfCells=getNumberOfCells();
2887   int ret=0;
2888   for(int i=0;i<nbOfCells;i++)
2889     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2890       ret++;
2891   return ret;
2892 }
2893
2894 /*!
2895  * Returns the nodal connectivity of a given cell.
2896  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2897  * all returned node ids can be used in getCoordinatesOfNode().
2898  *  \param [in] cellId - an id of the cell of interest.
2899  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2900  *         cleared before the appending.
2901  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2902  */
2903 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2904 {
2905   const int *ptI=_nodal_connec_index->getConstPointer();
2906   const int *pt=_nodal_connec->getConstPointer();
2907   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2908     if(*w>=0)
2909       conn.push_back(*w);
2910 }
2911
2912 std::string MEDCouplingUMesh::simpleRepr() const
2913 {
2914   static const char msg0[]="No coordinates specified !";
2915   std::ostringstream ret;
2916   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2917   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2918   int tmpp1,tmpp2;
2919   double tt=getTime(tmpp1,tmpp2);
2920   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2921   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2922   if(_mesh_dim>=-1)
2923     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2924   else
2925     { ret << " Mesh dimension has not been set or is invalid !"; }
2926   if(_coords!=0)
2927     {
2928       const int spaceDim=getSpaceDimension();
2929       ret << spaceDim << "\nInfo attached on space dimension : ";
2930       for(int i=0;i<spaceDim;i++)
2931         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2932       ret << "\n";
2933     }
2934   else
2935     ret << msg0 << "\n";
2936   ret << "Number of nodes : ";
2937   if(_coords!=0)
2938     ret << getNumberOfNodes() << "\n";
2939   else
2940     ret << msg0 << "\n";
2941   ret << "Number of cells : ";
2942   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2943     ret << getNumberOfCells() << "\n";
2944   else
2945     ret << "No connectivity specified !" << "\n";
2946   ret << "Cell types present : ";
2947   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2948     {
2949       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2950       ret << cm.getRepr() << " ";
2951     }
2952   ret << "\n";
2953   return ret.str();
2954 }
2955
2956 std::string MEDCouplingUMesh::advancedRepr() const
2957 {
2958   std::ostringstream ret;
2959   ret << simpleRepr();
2960   ret << "\nCoordinates array : \n___________________\n\n";
2961   if(_coords)
2962     _coords->reprWithoutNameStream(ret);
2963   else
2964     ret << "No array set !\n";
2965   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2966   reprConnectivityOfThisLL(ret);
2967   return ret.str();
2968 }
2969
2970 /*!
2971  * This method returns a C++ code that is a dump of \a this.
2972  * This method will throw if this is not fully defined.
2973  */
2974 std::string MEDCouplingUMesh::cppRepr() const
2975 {
2976   static const char coordsName[]="coords";
2977   static const char connName[]="conn";
2978   static const char connIName[]="connI";
2979   checkFullyDefined();
2980   std::ostringstream ret; ret << "// coordinates" << std::endl;
2981   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2982   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2983   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2984   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2985   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2986   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2987   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2988   return ret.str();
2989 }
2990
2991 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2992 {
2993   std::ostringstream ret;
2994   reprConnectivityOfThisLL(ret);
2995   return ret.str();
2996 }
2997
2998 /*!
2999  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3000  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3001  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3002  * some algos).
3003  * 
3004  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3005  * 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
3006  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3007  */
3008 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3009 {
3010   int mdim=getMeshDimension();
3011   if(mdim<0)
3012     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3013   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3014   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3015   bool needToCpyCT=true;
3016   if(!_nodal_connec)
3017     {
3018       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3019       needToCpyCT=false;
3020     }
3021   else
3022     {
3023       tmp1=_nodal_connec;
3024       tmp1->incrRef();
3025     }
3026   if(!_nodal_connec_index)
3027     {
3028       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3029       needToCpyCT=false;
3030     }
3031   else
3032     {
3033       tmp2=_nodal_connec_index;
3034       tmp2->incrRef();
3035     }
3036   ret->setConnectivity(tmp1,tmp2,false);
3037   if(needToCpyCT)
3038     ret->_types=_types;
3039   if(!_coords)
3040     {
3041       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3042       ret->setCoords(coords);
3043     }
3044   else
3045     ret->setCoords(_coords);
3046   return ret.retn();
3047 }
3048
3049 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3050 {
3051   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3052     {
3053       int nbOfCells=getNumberOfCells();
3054       const int *c=_nodal_connec->getConstPointer();
3055       const int *ci=_nodal_connec_index->getConstPointer();
3056       for(int i=0;i<nbOfCells;i++)
3057         {
3058           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3059           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3060           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3061           stream << "\n";
3062         }
3063     }
3064   else
3065     stream << "Connectivity not defined !\n";
3066 }
3067
3068 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3069 {
3070   const int *ptI=_nodal_connec_index->getConstPointer();
3071   const int *pt=_nodal_connec->getConstPointer();
3072   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3073     return ptI[cellId+1]-ptI[cellId]-1;
3074   else
3075     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3076 }
3077
3078 /*!
3079  * Returns types of cells of the specified part of \a this mesh.
3080  * This method avoids computing sub-mesh explicitely to get its types.
3081  *  \param [in] begin - an array of cell ids of interest.
3082  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3083  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3084  *         describing the cell types. 
3085  *  \throw If the coordinates array is not set.
3086  *  \throw If the nodal connectivity of cells is not defined.
3087  *  \sa getAllGeoTypes()
3088  */
3089 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3090 {
3091   checkFullyDefined();
3092   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3093   const int *conn=_nodal_connec->getConstPointer();
3094   const int *connIndex=_nodal_connec_index->getConstPointer();
3095   for(const int *w=begin;w!=end;w++)
3096     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3097   return ret;
3098 }
3099
3100 /*!
3101  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3102  * a set of types of cells constituting \a this mesh. 
3103  * This method is for advanced users having prepared their connectivity before. For
3104  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3105  *  \param [in] conn - the nodal connectivity array. 
3106  *  \param [in] connIndex - the nodal connectivity index array.
3107  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3108  *         mesh is updated.
3109  */
3110 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3111 {
3112   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3113   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3114   if(isComputingTypes)
3115     computeTypes();
3116   declareAsNew();
3117 }
3118
3119 /*!
3120  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3121  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3122  */
3123 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3124     _nodal_connec(0),_nodal_connec_index(0),
3125     _types(other._types)
3126 {
3127   if(other._nodal_connec)
3128     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3129   if(other._nodal_connec_index)
3130     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3131 }
3132
3133 MEDCouplingUMesh::~MEDCouplingUMesh()
3134 {
3135   if(_nodal_connec)
3136     _nodal_connec->decrRef();
3137   if(_nodal_connec_index)
3138     _nodal_connec_index->decrRef();
3139 }
3140
3141 /*!
3142  * Recomputes a set of cell types of \a this mesh. For more info see
3143  * \ref MEDCouplingUMeshNodalConnectivity.
3144  */
3145 void MEDCouplingUMesh::computeTypes()
3146 {
3147   if(_nodal_connec && _nodal_connec_index)
3148     {
3149       _types.clear();
3150       const int *conn=_nodal_connec->getConstPointer();
3151       const int *connIndex=_nodal_connec_index->getConstPointer();
3152       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3153       if (nbOfElem > 0)
3154         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3155           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3156     }
3157 }
3158
3159 /*!
3160  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3161  */
3162 void MEDCouplingUMesh::checkFullyDefined() const
3163 {
3164   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3165     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3166 }
3167
3168 /*!
3169  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3170  */
3171 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3172 {
3173   if(!_nodal_connec_index || !_nodal_connec)
3174     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3175 }
3176
3177 /*!
3178  * Returns a number of cells constituting \a this mesh. 
3179  *  \return int - the number of cells in \a this mesh.
3180  *  \throw If the nodal connectivity of cells is not defined.
3181  */
3182 int MEDCouplingUMesh::getNumberOfCells() const
3183
3184   if(_nodal_connec_index)
3185     return _nodal_connec_index->getNumberOfTuples()-1;
3186   else
3187     if(_mesh_dim==-1)
3188       return 1;
3189     else
3190       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3191 }
3192
3193 /*!
3194  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3195  * mesh. For more info see \ref MEDCouplingMeshesPage.
3196  *  \return int - the dimension of \a this mesh.
3197  *  \throw If the mesh dimension is not defined using setMeshDimension().
3198  */
3199 int MEDCouplingUMesh::getMeshDimension() const
3200 {
3201   if(_mesh_dim<-1)
3202     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3203   return _mesh_dim;
3204 }
3205
3206 /*!
3207  * Returns a length of the nodal connectivity array.
3208  * This method is for test reason. Normally the integer returned is not useable by
3209  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3210  *  \return int - the length of the nodal connectivity array.
3211  */
3212 int MEDCouplingUMesh::getMeshLength() const
3213 {
3214   return _nodal_connec->getNbOfElems();
3215 }
3216
3217 /*!
3218  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3219  */
3220 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3221 {
3222   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3223   tinyInfo.push_back(getMeshDimension());
3224   tinyInfo.push_back(getNumberOfCells());
3225   if(_nodal_connec)
3226     tinyInfo.push_back(getMeshLength());
3227   else
3228     tinyInfo.push_back(-1);
3229 }
3230
3231 /*!
3232  * First step of unserialization process.
3233  */
3234 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3235 {
3236   return tinyInfo[6]<=0;
3237 }
3238
3239 /*!
3240  * Second step of serialization process.
3241  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3242  */
3243 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3244 {
3245   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3246   if(tinyInfo[5]!=-1)
3247     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3248 }
3249
3250 /*!
3251  * Third and final step of serialization process.
3252  */
3253 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3254 {
3255   MEDCouplingPointSet::serialize(a1,a2);
3256   if(getMeshDimension()>-1)
3257     {
3258       a1=DataArrayInt::New();
3259       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3260       int *ptA1=a1->getPointer();
3261       const int *conn=getNodalConnectivity()->getConstPointer();
3262       const int *index=getNodalConnectivityIndex()->getConstPointer();
3263       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3264       std::copy(conn,conn+getMeshLength(),ptA1);
3265     }
3266   else
3267     a1=0;
3268 }
3269
3270 /*!
3271  * Second and final unserialization process.
3272  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3273  */
3274 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3275 {
3276   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3277   setMeshDimension(tinyInfo[5]);
3278   if(tinyInfo[7]!=-1)
3279     {
3280       // Connectivity
3281       const int *recvBuffer=a1->getConstPointer();
3282       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3283       myConnecIndex->alloc(tinyInfo[6]+1,1);
3284       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3285       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3286       myConnec->alloc(tinyInfo[7],1);
3287       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3288       setConnectivity(myConnec, myConnecIndex);
3289     }
3290 }
3291
3292 /*!
3293  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3294  * CellIds are given using range specified by a start an end and step.
3295  */
3296 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3297 {
3298   checkFullyDefined();
3299   int ncell=getNumberOfCells();
3300   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3301   ret->_mesh_dim=_mesh_dim;
3302   ret->setCoords(_coords);
3303   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3304   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3305   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3306   int work=start;
3307   const int *conn=_nodal_connec->getConstPointer();
3308   const int *connIndex=_nodal_connec_index->getConstPointer();
3309   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3310     {
3311       if(work>=0 && work<ncell)
3312         {
3313           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3314         }
3315       else
3316         {
3317           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3318           throw INTERP_KERNEL::Exception(oss.str().c_str());
3319         }
3320     }
3321   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3322   int *newConnPtr=newConn->getPointer();
3323   std::set<INTERP_KERNEL::NormalizedCellType> types;
3324   work=start;
3325   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3326     {
3327       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3328       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3329     }
3330   ret->setConnectivity(newConn,newConnI,false);
3331   ret->_types=types;
3332   ret->copyTinyInfoFrom(this);
3333   return ret.retn();
3334 }
3335
3336 /*!
3337  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3338  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3339  * The return newly allocated mesh will share the same coordinates as \a this.
3340  */
3341 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3342 {
3343   checkConnectivityFullyDefined();
3344   int ncell=getNumberOfCells();
3345   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3346   ret->_mesh_dim=_mesh_dim;
3347   ret->setCoords(_coords);
3348   std::size_t nbOfElemsRet=std::distance(begin,end);
3349   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3350   connIndexRet[0]=0;
3351   const int *conn=_nodal_connec->getConstPointer();
3352   const int *connIndex=_nodal_connec_index->getConstPointer();
3353   int newNbring=0;
3354   for(const int *work=begin;work!=end;work++,newNbring++)
3355     {
3356       if(*work>=0 && *work<ncell)
3357         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3358       else
3359         {
3360           free(connIndexRet);
3361           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3362           throw INTERP_KERNEL::Exception(oss.str().c_str());
3363         }
3364     }
3365   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3366   int *connRetWork=connRet;
3367   std::set<INTERP_KERNEL::NormalizedCellType> types;
3368   for(const int *work=begin;work!=end;work++)
3369     {
3370       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3371       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3372     }
3373   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3374   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3375   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3376   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3377   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3378   ret->_types=types;
3379   ret->copyTinyInfoFrom(this);
3380   return ret.retn();
3381 }
3382
3383 /*!
3384  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3385  * mesh.<br>
3386  * For 1D cells, the returned field contains lengths.<br>
3387  * For 2D cells, the returned field contains areas.<br>
3388  * For 3D cells, the returned field contains volumes.
3389  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3390  *         orientation, i.e. the volume is always positive.
3391  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3392  *         and one time . The caller is to delete this field using decrRef() as it is no
3393  *         more needed.
3394  */
3395 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3396 {
3397   std::string name="MeasureOfMesh_";
3398   name+=getName();
3399   int nbelem=getNumberOfCells();
3400   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3401   field->setName(name);
3402   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3403   array->alloc(nbelem,1);
3404   double *area_vol=array->getPointer();
3405   field->setArray(array) ; array=0;
3406   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3407   field->synchronizeTimeWithMesh();
3408   if(getMeshDimension()!=-1)
3409     {
3410       int ipt;
3411       INTERP_KERNEL::NormalizedCellType type;
3412       int dim_space=getSpaceDimension();
3413       const double *coords=getCoords()->getConstPointer();
3414       const int *connec=getNodalConnectivity()->getConstPointer();
3415       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3416       for(int iel=0;iel<nbelem;iel++)
3417         {
3418           ipt=connec_index[iel];
3419           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3420           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);
3421         }
3422       if(isAbs)
3423         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3424     }
3425   else
3426     {
3427       area_vol[0]=std::numeric_limits<double>::max();
3428     }
3429   return field.retn();
3430 }
3431
3432 /*!
3433  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3434  * mesh.<br>
3435  * For 1D cells, the returned array contains lengths.<br>
3436  * For 2D cells, the returned array contains areas.<br>
3437  * For 3D cells, the returned array contains volumes.
3438  * This method avoids building explicitly a part of \a this mesh to perform the work.
3439  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3440  *         orientation, i.e. the volume is always positive.
3441  *  \param [in] begin - an array of cell ids of interest.
3442  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3443  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3444  *          delete this array using decrRef() as it is no more needed.
3445  * 
3446  *  \if ENABLE_EXAMPLES
3447  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3448  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3449  *  \endif
3450  *  \sa getMeasureField()
3451  */
3452 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3453 {
3454   std::string name="PartMeasureOfMesh_";
3455   name+=getName();
3456   int nbelem=(int)std::distance(begin,end);
3457   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3458   array->setName(name);
3459   array->alloc(nbelem,1);
3460   double *area_vol=array->getPointer();
3461   if(getMeshDimension()!=-1)
3462     {
3463       int ipt;
3464       INTERP_KERNEL::NormalizedCellType type;
3465       int dim_space=getSpaceDimension();
3466       const double *coords=getCoords()->getConstPointer();
3467       const int *connec=getNodalConnectivity()->getConstPointer();
3468       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3469       for(const int *iel=begin;iel!=end;iel++)
3470         {
3471           ipt=connec_index[*iel];
3472           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3473           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3474         }
3475       if(isAbs)
3476         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3477     }
3478   else
3479     {
3480       area_vol[0]=std::numeric_limits<double>::max();
3481     }
3482   return array.retn();
3483 }
3484
3485 /*!
3486  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3487  * \a this one. The returned field contains the dual cell volume for each corresponding
3488  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3489  *  the dual mesh in P1 sens of \a this.<br>
3490  * For 1D cells, the returned field contains lengths.<br>
3491  * For 2D cells, the returned field contains areas.<br>
3492  * For 3D cells, the returned field contains volumes.
3493  * This method is useful to check "P1*" conservative interpolators.
3494  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3495  *         orientation, i.e. the volume is always positive.
3496  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3497  *          nodes and one time. The caller is to delete this array using decrRef() as
3498  *          it is no more needed.
3499  */
3500 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3501 {
3502   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3503   std::string name="MeasureOnNodeOfMesh_";
3504   name+=getName();
3505   int nbNodes=getNumberOfNodes();
3506   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3507   double cst=1./((double)getMeshDimension()+1.);
3508   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3509   array->alloc(nbNodes,1);
3510   double *valsToFill=array->getPointer();
3511   std::fill(valsToFill,valsToFill+nbNodes,0.);
3512   const double *values=tmp->getArray()->getConstPointer();
3513   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3515   getReverseNodalConnectivity(da,daInd);
3516   const int *daPtr=da->getConstPointer();
3517   const int *daIPtr=daInd->getConstPointer();
3518   for(int i=0;i<nbNodes;i++)
3519     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3520       valsToFill[i]+=cst*values[*cell];
3521   ret->setMesh(this);
3522   ret->setArray(array);
3523   return ret.retn();
3524 }
3525
3526 /*!
3527  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3528  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3529  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3530  * and are normalized.
3531  * <br> \a this can be either 
3532  * - a  2D mesh in 2D or 3D space or 
3533  * - an 1D mesh in 2D space.
3534  * 
3535  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3536  *          cells and one time. The caller is to delete this field using decrRef() as
3537  *          it is no more needed.
3538  *  \throw If the nodal connectivity of cells is not defined.
3539  *  \throw If the coordinates array is not set.
3540  *  \throw If the mesh dimension is not set.
3541  *  \throw If the mesh and space dimension is not as specified above.
3542  */
3543 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3544 {
3545   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3546     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3547   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3548   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3549   int nbOfCells=getNumberOfCells();
3550   int nbComp=getMeshDimension()+1;
3551   array->alloc(nbOfCells,nbComp);
3552   double *vals=array->getPointer();
3553   const int *connI=_nodal_connec_index->getConstPointer();
3554   const int *conn=_nodal_connec->getConstPointer();
3555   const double *coords=_coords->getConstPointer();
3556   if(getMeshDimension()==2)
3557     {
3558       if(getSpaceDimension()==3)
3559         {
3560           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3561           const double *locPtr=loc->getConstPointer();
3562           for(int i=0;i<nbOfCells;i++,vals+=3)
3563             {
3564               int offset=connI[i];
3565               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3566               double n=INTERP_KERNEL::norm<3>(vals);
3567               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3568             }
3569         }
3570       else
3571         {
3572           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3573           const double *isAbsPtr=isAbs->getArray()->begin();
3574           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3575             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3576         }
3577     }
3578   else//meshdimension==1
3579     {
3580       double tmp[2];
3581       for(int i=0;i<nbOfCells;i++)
3582         {
3583           int offset=connI[i];
3584           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3585           double n=INTERP_KERNEL::norm<2>(tmp);
3586           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3587           *vals++=-tmp[1];
3588           *vals++=tmp[0];
3589         }
3590     }
3591   ret->setArray(array);
3592   ret->setMesh(this);
3593   ret->synchronizeTimeWithSupport();
3594   return ret.retn();
3595 }
3596
3597 /*!
3598  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3599  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3600  * and are normalized.
3601  * <br> \a this can be either 
3602  * - a  2D mesh in 2D or 3D space or 
3603  * - an 1D mesh in 2D space.
3604  * 
3605  * This method avoids building explicitly a part of \a this mesh to perform the work.
3606  *  \param [in] begin - an array of cell ids of interest.
3607  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3608  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3609  *          cells and one time. The caller is to delete this field using decrRef() as
3610  *          it is no more needed.
3611  *  \throw If the nodal connectivity of cells is not defined.
3612  *  \throw If the coordinates array is not set.
3613  *  \throw If the mesh dimension is not set.
3614  *  \throw If the mesh and space dimension is not as specified above.
3615  *  \sa buildOrthogonalField()
3616  *
3617  *  \if ENABLE_EXAMPLES
3618  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3619  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3620  *  \endif
3621  */
3622 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3623 {
3624   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3625     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3626   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3627   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3628   std::size_t nbelems=std::distance(begin,end);
3629   int nbComp=getMeshDimension()+1;
3630   array->alloc((int)nbelems,nbComp);
3631   double *vals=array->getPointer();
3632   const int *connI=_nodal_connec_index->getConstPointer();
3633   const int *conn=_nodal_connec->getConstPointer();
3634   const double *coords=_coords->getConstPointer();
3635   if(getMeshDimension()==2)
3636     {
3637       if(getSpaceDimension()==3)
3638         {
3639           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3640           const double *locPtr=loc->getConstPointer();
3641           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3642             {
3643               int offset=connI[*i];
3644               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3645               double n=INTERP_KERNEL::norm<3>(vals);
3646               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3647             }
3648         }
3649       else
3650         {
3651           for(std::size_t i=0;i<nbelems;i++)
3652             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3653         }
3654     }
3655   else//meshdimension==1
3656     {
3657       double tmp[2];
3658       for(const int *i=begin;i!=end;i++)
3659         {
3660           int offset=connI[*i];
3661           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3662           double n=INTERP_KERNEL::norm<2>(tmp);
3663           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3664           *vals++=-tmp[1];
3665           *vals++=tmp[0];
3666         }
3667     }
3668   ret->setArray(array);
3669   ret->setMesh(this);
3670   ret->synchronizeTimeWithSupport();
3671   return ret.retn();
3672 }
3673
3674 /*!
3675  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3676  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3677  * and are \b not normalized.
3678  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3679  *          cells and one time. The caller is to delete this field using decrRef() as
3680  *          it is no more needed.
3681  *  \throw If the nodal connectivity of cells is not defined.
3682  *  \throw If the coordinates array is not set.
3683  *  \throw If \a this->getMeshDimension() != 1.
3684  *  \throw If \a this mesh includes cells of type other than SEG2.
3685  */
3686 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3687 {
3688   if(getMeshDimension()!=1)
3689     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3690   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3691     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3692   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3693   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3694   int nbOfCells=getNumberOfCells();
3695   int spaceDim=getSpaceDimension();
3696   array->alloc(nbOfCells,spaceDim);
3697   double *pt=array->getPointer();
3698   const double *coo=getCoords()->getConstPointer();
3699   std::vector<int> conn;
3700   conn.reserve(2);
3701   for(int i=0;i<nbOfCells;i++)
3702     {
3703       conn.resize(0);
3704       getNodeIdsOfCell(i,conn);
3705       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3706     }
3707   ret->setArray(array);
3708   ret->setMesh(this);
3709   ret->synchronizeTimeWithSupport();
3710   return ret.retn();
3711 }
3712
3713 /*!
3714  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3715  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3716  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3717  * from. If a result face is shared by two 3D cells, then the face in included twice in
3718  * the result mesh.
3719  *  \param [in] origin - 3 components of a point defining location of the plane.
3720  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3721  *         must be greater than 1e-6.
3722  *  \param [in] eps - half-thickness of the plane.
3723  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3724  *         producing correspondent 2D cells. The caller is to delete this array
3725  *         using decrRef() as it is no more needed.
3726  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3727  *         not share the node coordinates array with \a this mesh. The caller is to
3728  *         delete this mesh using decrRef() as it is no more needed.  
3729  *  \throw If the coordinates array is not set.
3730  *  \throw If the nodal connectivity of cells is not defined.
3731  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3732  *  \throw If magnitude of \a vec is less than 1e-6.
3733  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3734  *  \throw If \a this includes quadratic cells.
3735  */
3736 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3737 {
3738   checkFullyDefined();
3739   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3740     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3741   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3742   if(candidates->empty())
3743     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3744   std::vector<int> nodes;
3745   DataArrayInt *cellIds1D=0;
3746   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3747   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3748   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3749   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3750   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3752   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3753   revDesc2=0; revDescIndx2=0;
3754   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3755   revDesc1=0; revDescIndx1=0;
3756   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3757   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3758   //
3759   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3760   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3761     cut3DCurve[*it]=-1;
3762   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3763   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3764   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3765                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3766                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3767   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3768   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3769   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3770   if(cellIds2->empty())
3771     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3772   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3773   ret->setCoords(mDesc1->getCoords());
3774   ret->setConnectivity(conn,connI,true);
3775   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3776   return ret.retn();
3777 }
3778
3779 /*!
3780  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3781 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
3782 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3783 the result mesh.
3784  *  \param [in] origin - 3 components of a point defining location of the plane.
3785  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3786  *         must be greater than 1e-6.
3787  *  \param [in] eps - half-thickness of the plane.
3788  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3789  *         producing correspondent segments. The caller is to delete this array
3790  *         using decrRef() as it is no more needed.
3791  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3792  *         mesh in 3D space. This mesh does not share the node coordinates array with
3793  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3794  *         no more needed. 
3795  *  \throw If the coordinates array is not set.
3796  *  \throw If the nodal connectivity of cells is not defined.
3797  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3798  *  \throw If magnitude of \a vec is less than 1e-6.
3799  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3800  *  \throw If \a this includes quadratic cells.
3801  */
3802 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3803 {
3804   checkFullyDefined();
3805   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3806     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3807   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3808   if(candidates->empty())
3809     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3810   std::vector<int> nodes;
3811   DataArrayInt *cellIds1D=0;
3812   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3813   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3814   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3815   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3816   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3817   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3818   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3819   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3821   //
3822   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3823   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3824     cut3DCurve[*it]=-1;
3825   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3826   int ncellsSub=subMesh->getNumberOfCells();
3827   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3828   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3829                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3830                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3831   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3832   conn->alloc(0,1);
3833   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3834   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3835   for(int i=0;i<ncellsSub;i++)
3836     {
3837       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3838         {
3839           if(cut3DSurf[i].first!=-2)
3840             {
3841               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3842               connI->pushBackSilent(conn->getNumberOfTuples());
3843               cellIds2->pushBackSilent(i);
3844             }
3845           else
3846             {
3847               int cellId3DSurf=cut3DSurf[i].second;
3848               int offset=nodalI[cellId3DSurf]+1;
3849               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3850               for(int j=0;j<nbOfEdges;j++)
3851                 {
3852                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3853                   connI->pushBackSilent(conn->getNumberOfTuples());
3854                   cellIds2->pushBackSilent(cellId3DSurf);
3855                 }
3856             }
3857         }
3858     }
3859   if(cellIds2->empty())
3860     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3861   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3862   ret->setCoords(mDesc1->getCoords());
3863   ret->setConnectivity(conn,connI,true);
3864   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3865   return ret.retn();
3866 }
3867
3868 /*!
3869  * Finds cells whose bounding boxes intersect a given plane.
3870  *  \param [in] origin - 3 components of a point defining location of the plane.
3871  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3872  *         must be greater than 1e-6.
3873  *  \param [in] eps - half-thickness of the plane.
3874  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3875  *         cells. The caller is to delete this array using decrRef() as it is no more
3876  *         needed.
3877  *  \throw If the coordinates array is not set.
3878  *  \throw If the nodal connectivity of cells is not defined.
3879  *  \throw If \a this->getSpaceDimension() != 3.
3880  *  \throw If magnitude of \a vec is less than 1e-6.
3881  *  \sa buildSlice3D()
3882  */
3883 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3884 {
3885   checkFullyDefined();
3886   if(getSpaceDimension()!=3)
3887     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3888   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3889   if(normm<1e-6)
3890     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3891   double vec2[3];
3892   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3893   double angle=acos(vec[2]/normm);
3894   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3895   double bbox[6];
3896   if(angle>eps)
3897     {
3898       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3899       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3900       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3901       mw->setCoords(coo);
3902       mw->getBoundingBox(bbox);
3903       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3904       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3905     }
3906   else
3907     {
3908       getBoundingBox(bbox);
3909       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3910       cellIds=getCellsInBoundingBox(bbox,eps);
3911     }
3912   return cellIds.retn();
3913 }
3914
3915 /*!
3916  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3917  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3918  * No consideration of coordinate is done by this method.
3919  * 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)
3920  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3921  */
3922 bool MEDCouplingUMesh::isContiguous1D() const
3923 {
3924   if(getMeshDimension()!=1)
3925     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3926   int nbCells=getNumberOfCells();
3927   if(nbCells<1)
3928     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3929   const int *connI=_nodal_connec_index->getConstPointer();
3930   const int *conn=_nodal_connec->getConstPointer();
3931   int ref=conn[connI[0]+2];
3932   for(int i=1;i<nbCells;i++)
3933     {
3934       if(conn[connI[i]+1]!=ref)
3935         return false;
3936       ref=conn[connI[i]+2];
3937     }
3938   return true;
3939 }
3940
3941 /*!
3942  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3943  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3944  * \param pt reference point of the line
3945  * \param v normalized director vector of the line
3946  * \param eps max precision before throwing an exception
3947  * \param res output of size this->getNumberOfCells
3948  */
3949 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3950 {
3951   if(getMeshDimension()!=1)
3952     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3953   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3954     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3955   if(getSpaceDimension()!=3)
3956     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3957   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3958   const double *fPtr=f->getArray()->getConstPointer();
3959   double tmp[3];
3960   for(int i=0;i<getNumberOfCells();i++)
3961     {
3962       const double *tmp1=fPtr+3*i;
3963       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3964       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3965       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3966       double n1=INTERP_KERNEL::norm<3>(tmp);
3967       n1/=INTERP_KERNEL::norm<3>(tmp1);
3968       if(n1>eps)
3969         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3970     }
3971   const double *coo=getCoords()->getConstPointer();
3972   for(int i=0;i<getNumberOfNodes();i++)
3973     {
3974       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3975       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3976       res[i]=std::accumulate(tmp,tmp+3,0.);
3977     }
3978 }
3979
3980 /*!
3981  * 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. 
3982  * \a this is expected to be a mesh so that its space dimension is equal to its
3983  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3984  * 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).
3985  *
3986  * 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
3987  * 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).
3988  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3989  *
3990  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3991  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3992  *
3993  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3994  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3995  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3996  * \return the positive value of the distance.
3997  * \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
3998  * dimension - 1.
3999  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4000  */
4001 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4002 {
4003   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4004   if(meshDim!=spaceDim-1)
4005     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4006   if(meshDim!=2 && meshDim!=1)
4007     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4008   checkFullyDefined();
4009   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4010     { 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()); }
4011   DataArrayInt *ret1=0;
4012   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4013   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4014   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4015   cellId=*ret1Safe->begin();
4016   return *ret0->begin();
4017 }
4018
4019 /*!
4020  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4021  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4022  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
4023  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
4024  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4025  * 
4026  * \a this is expected to be a mesh so that its space dimension is equal to its
4027  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4028  * 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).
4029  *
4030  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4031  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4032  *
4033  * \param [in] pts the list of points in which each tuple represents a point
4034  * \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.
4035  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4036  * \throw if number of components of \a pts is not equal to the space dimension.
4037  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4038  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4039  */
4040 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4041 {
4042   if(!pts)
4043     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4044   pts->checkAllocated();
4045   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4046   if(meshDim!=spaceDim-1)
4047     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4048   if(meshDim!=2 && meshDim!=1)
4049     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4050   if(pts->getNumberOfComponents()!=spaceDim)
4051     {
4052       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4053       throw INTERP_KERNEL::Exception(oss.str().c_str());
4054     }
4055   checkFullyDefined();
4056   int nbCells=getNumberOfCells();
4057   if(nbCells==0)
4058     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4059   int nbOfPts=pts->getNumberOfTuples();
4060   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4061   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4062   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4063   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4064   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4065   const double *bbox(bboxArr->begin());
4066   switch(spaceDim)
4067   {
4068     case 3:
4069       {
4070         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4071         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4072           {
4073             double x=std::numeric_limits<double>::max();
4074             std::vector<int> elems;
4075             myTree.getMinDistanceOfMax(ptsPtr,x);
4076             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4077             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4078           }
4079         break;
4080       }
4081     case 2:
4082       {
4083         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4084         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4085           {
4086             double x=std::numeric_limits<double>::max();
4087             std::vector<int> elems;
4088             myTree.getMinDistanceOfMax(ptsPtr,x);
4089             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4090             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4091           }
4092         break;
4093       }
4094     default:
4095       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4096   }
4097   cellIds=ret1.retn();
4098   return ret0.retn();
4099 }
4100
4101 /*!
4102  * \param [in] pt the start pointer (included) of the coordinates of the point
4103  * \param [in] cellIdsBg the start pointer (included) of cellIds
4104  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4105  * \param [in] nc nodal connectivity
4106  * \param [in] ncI nodal connectivity index
4107  * \param [in,out] ret0 the min distance between \a this and the external input point
4108  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4109  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4110  */
4111 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)
4112 {
4113   cellId=-1;
4114   ret0=std::numeric_limits<double>::max();
4115   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4116     {
4117       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4118       {
4119         case INTERP_KERNEL::NORM_TRI3:
4120           {
4121             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4122             if(tmp<ret0)
4123               { ret0=tmp; cellId=*zeCell; }
4124             break;
4125           }
4126         case INTERP_KERNEL::NORM_QUAD4:
4127         case INTERP_KERNEL::NORM_POLYGON:
4128           {
4129             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4130             if(tmp<ret0)
4131               { ret0=tmp; cellId=*zeCell; }
4132             break;
4133           }
4134         default:
4135           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4136       }
4137     }
4138 }
4139
4140 /*!
4141  * \param [in] pt the start pointer (included) of the coordinates of the point
4142  * \param [in] cellIdsBg the start pointer (included) of cellIds
4143  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4144  * \param [in] nc nodal connectivity
4145  * \param [in] ncI nodal connectivity index
4146  * \param [in,out] ret0 the min distance between \a this and the external input point
4147  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4148  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4149  */
4150 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)
4151 {
4152   cellId=-1;
4153   ret0=std::numeric_limits<double>::max();
4154   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4155     {
4156       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4157       {
4158         case INTERP_KERNEL::NORM_SEG2:
4159           {
4160             std::size_t uselessEntry=0;
4161             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4162             tmp=sqrt(tmp);
4163             if(tmp<ret0)
4164               { ret0=tmp; cellId=*zeCell; }
4165             break;
4166           }
4167         default:
4168           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4169       }
4170     }
4171 }
4172
4173 /*!
4174  * Finds cells in contact with a ball (i.e. a point with precision). 
4175  * 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.
4176  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4177  *
4178  * \warning This method is suitable if the caller intends to evaluate only one
4179  *          point, for more points getCellsContainingPoints() is recommended as it is
4180  *          faster. 
4181  *  \param [in] pos - array of coordinates of the ball central point.
4182  *  \param [in] eps - ball radius.
4183  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4184  *         if there are no such cells.
4185  *  \throw If the coordinates array is not set.
4186  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4187  */
4188 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4189 {
4190   std::vector<int> elts;
4191   getCellsContainingPoint(pos,eps,elts);
4192   if(elts.empty())
4193     return -1;
4194   return elts.front();
4195 }
4196
4197 /*!
4198  * Finds cells in contact with a ball (i.e. a point with precision).
4199  * 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.
4200  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4201  * \warning This method is suitable if the caller intends to evaluate only one
4202  *          point, for more points getCellsContainingPoints() is recommended as it is
4203  *          faster. 
4204  *  \param [in] pos - array of coordinates of the ball central point.
4205  *  \param [in] eps - ball radius.
4206  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4207  *         before inserting ids.
4208  *  \throw If the coordinates array is not set.
4209  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4210  *
4211  *  \if ENABLE_EXAMPLES
4212  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4213  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4214  *  \endif
4215  */
4216 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4217 {
4218   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4219   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4220   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4221 }
4222
4223 /// @cond INTERNAL
4224
4225 namespace ParaMEDMEM
4226 {
4227   template<const int SPACEDIMM>
4228   class DummyClsMCUG
4229   {
4230   public:
4231     static const int MY_SPACEDIM=SPACEDIMM;
4232     static const int MY_MESHDIM=8;
4233     typedef int MyConnType;
4234     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4235     // begin
4236     // useless, but for windows compilation ...
4237     const double* getCoordinatesPtr() const { return 0; }
4238     const int* getConnectivityPtr() const { return 0; }
4239     const int* getConnectivityIndexPtr() const { return 0; }
4240     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4241     // end
4242   };
4243
4244
4245
4246   /*!
4247    * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4248    */
4249   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4250   {
4251     INTERP_KERNEL::Edge *ret(0);
4252     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]));
4253     m[n0]=bg[0]; m[n1]=bg[1];
4254     switch(typ)
4255     {
4256       case INTERP_KERNEL::NORM_SEG2:
4257         {
4258           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4259           break;
4260         }
4261       case INTERP_KERNEL::NORM_SEG3:
4262         {
4263           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4264           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4265           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4266           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4267           bool colinearity(inters.areColinears());
4268           delete e1; delete e2;
4269           if(colinearity)
4270             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4271           else
4272             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4273           break;
4274         }
4275       default:
4276         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4277     }
4278     return ret;
4279   }
4280
4281   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4282   {
4283     INTERP_KERNEL::Edge *ret=0;
4284     switch(typ)
4285     {
4286       case INTERP_KERNEL::NORM_SEG2:
4287         {
4288           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4289           break;
4290         }
4291       case INTERP_KERNEL::NORM_SEG3:
4292         {
4293           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4294           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4295           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4296           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4297           bool colinearity=inters.areColinears();
4298           delete e1; delete e2;
4299           if(colinearity)
4300             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4301           else
4302             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4303           mapp2[bg[2]].second=false;
4304           break;
4305         }
4306       default:
4307         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4308     }
4309     return ret;
4310   }
4311
4312   /*!
4313    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4314    * the global mesh 'mDesc'.
4315    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4316    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4317    */
4318   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4319                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4320   {
4321     mapp.clear();
4322     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.
4323     const double *coo=mDesc->getCoords()->getConstPointer();
4324     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4325     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4326     std::set<int> s;
4327     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4328       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4329     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4330       {
4331         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4332         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4333       }
4334     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4335     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4336       {
4337         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4338         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4339       }
4340     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4341       {
4342         if((*it2).second.second)
4343           mapp[(*it2).second.first]=(*it2).first;
4344         ((*it2).second.first)->decrRef();
4345       }
4346     return ret;
4347   }
4348
4349   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4350   {
4351     if(nodeId>=offset2)
4352       {
4353         int locId=nodeId-offset2;
4354         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4355       }
4356     if(nodeId>=offset1)
4357       {
4358         int locId=nodeId-offset1;
4359         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4360       }
4361     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4362   }
4363
4364   /**
4365    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4366    */
4367   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4368                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4369                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4370   {
4371     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4372       {
4373         int eltId1=abs(*desc1)-1;
4374         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4375           {
4376             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4377             if(it==mappRev.end())
4378               {
4379                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4380                 mapp[node]=*it1;
4381                 mappRev[*it1]=node;
4382               }
4383           }
4384       }
4385   }
4386 }
4387
4388 /// @endcond
4389
4390 template<int SPACEDIM>
4391 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4392                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4393 {
4394   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4395   int *eltsIndexPtr(eltsIndex->getPointer());
4396   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4397   const double *bbox(bboxArr->begin());
4398   int nbOfCells=getNumberOfCells();
4399   const int *conn=_nodal_connec->getConstPointer();
4400   const int *connI=_nodal_connec_index->getConstPointer();
4401   double bb[2*SPACEDIM];
4402   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4403   for(int i=0;i<nbOfPoints;i++)
4404     {
4405       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4406       for(int j=0;j<SPACEDIM;j++)
4407         {
4408           bb[2*j]=pos[SPACEDIM*i+j];
4409           bb[2*j+1]=pos[SPACEDIM*i+j];
4410         }
4411       std::vector<int> candidates;
4412       myTree.getIntersectingElems(bb,candidates);
4413       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4414         {
4415           int sz(connI[(*iter)+1]-connI[*iter]-1);
4416           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4417           bool status(false);
4418           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4419             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4420           else
4421             {
4422               if(SPACEDIM!=2)
4423                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4424               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4425               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4426               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4427               INTERP_KERNEL::QuadraticPolygon *pol(0);
4428               for(int j=0;j<sz;j++)
4429                 {
4430                   int nodeId(conn[connI[*iter]+1+j]);
4431                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4432                 }
4433               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4434                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4435               else
4436                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4437               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4438               double a(0.),b(0.),c(0.);
4439               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4440               status=pol->isInOrOut2(n);
4441               delete pol; n->decrRef();
4442             }
4443           if(status)
4444             {
4445               eltsIndexPtr[i+1]++;
4446               elts->pushBackSilent(*iter);
4447             }
4448         }
4449     }
4450 }
4451 /*!
4452  * Finds cells in contact with several balls (i.e. points with precision).
4453  * This method is an extension of getCellContainingPoint() and
4454  * getCellsContainingPoint() for the case of multiple points.
4455  * 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.
4456  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4457  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4458  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4459  *         this->getSpaceDimension() * \a nbOfPoints 
4460  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4461  *  \param [in] eps - radius of balls (i.e. the precision).
4462  *  \param [out] elts - vector returning ids of found cells.
4463  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4464  *         dividing cell ids in \a elts into groups each referring to one
4465  *         point. Its every element (except the last one) is an index pointing to the
4466  *         first id of a group of cells. For example cells in contact with the *i*-th
4467  *         point are described by following range of indices:
4468  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4469  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4470  *         Number of cells in contact with the *i*-th point is
4471  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4472  *  \throw If the coordinates array is not set.
4473  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4474  *
4475  *  \if ENABLE_EXAMPLES
4476  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4477  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4478  *  \endif
4479  */
4480 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4481                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4482 {
4483   int spaceDim=getSpaceDimension();
4484   int mDim=getMeshDimension();
4485   if(spaceDim==3)
4486     {
4487       if(mDim==3)
4488         {
4489           const double *coords=_coords->getConstPointer();
4490           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4491         }
4492       /*else if(mDim==2)
4493         {
4494
4495         }*/
4496       else
4497         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4498     }
4499   else if(spaceDim==2)
4500     {
4501       if(mDim==2)
4502         {
4503           const double *coords=_coords->getConstPointer();
4504           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4505         }
4506       else
4507         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4508     }
4509   else if(spaceDim==1)
4510     {
4511       if(mDim==1)
4512         {
4513           const double *coords=_coords->getConstPointer();
4514           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4515         }
4516       else
4517         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4518     }
4519   else
4520     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4521 }
4522
4523 /*!
4524  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4525  * least two its edges intersect each other anywhere except their extremities. An
4526  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4527  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4528  *         cleared before filling in.
4529  *  \param [in] eps - precision.
4530  *  \throw If \a this->getMeshDimension() != 2.
4531  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4532  */
4533 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4534 {
4535   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4536   if(getMeshDimension()!=2)
4537     throw INTERP_KERNEL::Exception(msg);
4538   int spaceDim=getSpaceDimension();
4539   if(spaceDim!=2 && spaceDim!=3)
4540     throw INTERP_KERNEL::Exception(msg);
4541   const int *conn=_nodal_connec->getConstPointer();
4542   const int *connI=_nodal_connec_index->getConstPointer();
4543   int nbOfCells=getNumberOfCells();
4544   std::vector<double> cell2DinS2;
4545   for(int i=0;i<nbOfCells;i++)
4546     {
4547       int offset=connI[i];
4548       int nbOfNodesForCell=connI[i+1]-offset-1;
4549       if(nbOfNodesForCell<=3)
4550         continue;
4551       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4552       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4553       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4554         cells.push_back(i);
4555       cell2DinS2.clear();
4556     }
4557 }
4558
4559 /*!
4560  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4561  *
4562  * 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.
4563  * 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.
4564  * 
4565  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4566  * This convex envelop is computed using Jarvis march algorithm.
4567  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4568  * 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)
4569  * 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.
4570  *
4571  * \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.
4572  * \sa MEDCouplingUMesh::colinearize2D
4573  */
4574 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4575 {
4576   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4577     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4578   checkFullyDefined();
4579   const double *coords=getCoords()->getConstPointer();
4580   int nbOfCells=getNumberOfCells();
4581   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4582   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4583   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4584   int *workIndexOut=nodalConnecIndexOut->getPointer();
4585   *workIndexOut=0;
4586   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4587   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4588   std::set<INTERP_KERNEL::NormalizedCellType> types;
4589   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4590   isChanged->alloc(0,1);
4591   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4592     {
4593       int pos=nodalConnecOut->getNumberOfTuples();
4594       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4595         isChanged->pushBackSilent(i);
4596       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4597       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4598     }
4599   if(isChanged->empty())
4600     return 0;
4601   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4602   _types=types;
4603   return isChanged.retn();
4604 }
4605
4606 /*!
4607  * This method is \b NOT const because it can modify \a this.
4608  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4609  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4610  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4611  * \b 1 for translation and rotation around point of 'mesh1D'.
4612  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4613  */
4614 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4615 {
4616   checkFullyDefined();
4617   mesh1D->checkFullyDefined();
4618   if(!mesh1D->isContiguous1D())
4619     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4620   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4621     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4622   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4623     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4624   if(mesh1D->getMeshDimension()!=1)
4625     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4626   bool isQuad=false;
4627   if(isPresenceOfQuadratic())
4628     {
4629       if(mesh1D->isFullyQuadratic())
4630         isQuad=true;
4631       else
4632         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4633     }
4634   zipCoords();
4635   int oldNbOfNodes=getNumberOfNodes();
4636   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4637   switch(policy)
4638   {
4639     case 0:
4640       {
4641         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4642         break;
4643       }
4644     case 1:
4645       {
4646         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4647         break;
4648       }
4649     default:
4650       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4651   }
4652   setCoords(newCoords);
4653   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4654   updateTime();
4655   return ret.retn();
4656 }
4657
4658 /*!
4659  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4660  * If it is not the case an exception will be thrown.
4661  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4662  * intersection of plane defined by ('origin','vec').
4663  * This method has one in/out parameter : 'cut3DCurve'.
4664  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4665  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4666  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4667  * This method will throw an exception if \a this contains a non linear segment.
4668  */
4669 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4670 {
4671   checkFullyDefined();
4672   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4673     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4674   int ncells=getNumberOfCells();
4675   int nnodes=getNumberOfNodes();
4676   double vec2[3],vec3[3],vec4[3];
4677   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4678   if(normm<1e-6)
4679     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4680   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4681   const int *conn=_nodal_connec->getConstPointer();
4682   const int *connI=_nodal_connec_index->getConstPointer();
4683   const double *coo=_coords->getConstPointer();
4684   std::vector<double> addCoo;
4685   for(int i=0;i<ncells;i++)
4686     {
4687       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4688         {
4689           if(cut3DCurve[i]==-2)
4690             {
4691               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4692               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];
4693               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4694               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4695               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4696                 {
4697                   const double *st2=coo+3*st;
4698                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4699                   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]));
4700                   if(pos>eps && pos<1-eps)
4701                     {
4702                       int nNode=((int)addCoo.size())/3;
4703                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4704                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4705                       cut3DCurve[i]=nnodes+nNode;
4706                     }
4707                 }
4708             }
4709         }
4710       else
4711         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4712     }
4713   if(!addCoo.empty())
4714     {
4715       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4716       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4717       coo2->alloc(newNbOfNodes,3);
4718       double *tmp=coo2->getPointer();
4719       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4720       std::copy(addCoo.begin(),addCoo.end(),tmp);
4721       DataArrayDouble::SetArrayIn(coo2,_coords);
4722     }
4723 }
4724
4725 /*!
4726  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4727  * \param mesh1D is the input 1D mesh used for translation computation.
4728  * \return newCoords new coords filled by this method. 
4729  */
4730 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4731 {
4732   int oldNbOfNodes=getNumberOfNodes();
4733   int nbOf1DCells=mesh1D->getNumberOfCells();
4734   int spaceDim=getSpaceDimension();
4735   DataArrayDouble *ret=DataArrayDouble::New();
4736   std::vector<bool> isQuads;
4737   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4738   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4739   double *retPtr=ret->getPointer();
4740   const double *coords=getCoords()->getConstPointer();
4741   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4742   std::vector<int> v;
4743   std::vector<double> c;
4744   double vec[3];
4745   v.reserve(3);
4746   c.reserve(6);
4747   for(int i=0;i<nbOf1DCells;i++)
4748     {
4749       v.resize(0);
4750       mesh1D->getNodeIdsOfCell(i,v);
4751       c.resize(0);
4752       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4753       mesh1D->getCoordinatesOfNode(v[0],c);
4754       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4755       for(int j=0;j<oldNbOfNodes;j++)
4756         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4757       if(isQuad)
4758         {
4759           c.resize(0);
4760           mesh1D->getCoordinatesOfNode(v[1],c);
4761           mesh1D->getCoordinatesOfNode(v[0],c);
4762           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4763           for(int j=0;j<oldNbOfNodes;j++)
4764             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4765         }
4766     }
4767   ret->copyStringInfoFrom(*getCoords());
4768   return ret;
4769 }
4770
4771 /*!
4772  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4773  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4774  * \return newCoords new coords filled by this method. 
4775  */
4776 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4777 {
4778   if(mesh1D->getSpaceDimension()==2)
4779     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4780   if(mesh1D->getSpaceDimension()==3)
4781     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4782   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4783 }
4784
4785 /*!
4786  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4787  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4788  * \return newCoords new coords filled by this method. 
4789  */
4790 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4791 {
4792   if(isQuad)
4793     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4794   int oldNbOfNodes=getNumberOfNodes();
4795   int nbOf1DCells=mesh1D->getNumberOfCells();
4796   if(nbOf1DCells<2)
4797     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4798   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4799   int nbOfLevsInVec=nbOf1DCells+1;
4800   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4801   double *retPtr=ret->getPointer();
4802   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4803   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4804   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4805   tmp->setCoords(tmp2);
4806   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4807   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4808   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4809   for(int i=1;i<nbOfLevsInVec;i++)
4810     {
4811       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4812       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4813       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4814       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4815       tmp->translate(vec);
4816       double tmp3[2],radius,alpha,alpha0;
4817       const double *p0=i+1<nbOfLevsInVec?begin:third;
4818       const double *p1=i+1<nbOfLevsInVec?end:begin;
4819       const double *p2=i+1<nbOfLevsInVec?third:end;
4820       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4821       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]);
4822       double angle=acos(cosangle/(radius*radius));
4823       tmp->rotate(end,0,angle);
4824       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4825     }
4826   return ret.retn();
4827 }
4828
4829 /*!
4830  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4831  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4832  * \return newCoords new coords filled by this method. 
4833  */
4834 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4835 {
4836   if(isQuad)
4837     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4838   int oldNbOfNodes=getNumberOfNodes();
4839   int nbOf1DCells=mesh1D->getNumberOfCells();
4840   if(nbOf1DCells<2)
4841     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4842   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4843   int nbOfLevsInVec=nbOf1DCells+1;
4844   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4845   double *retPtr=ret->getPointer();
4846   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4847   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4848   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4849   tmp->setCoords(tmp2);
4850   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4851   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4852   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4853   for(int i=1;i<nbOfLevsInVec;i++)
4854     {
4855       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4856       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4857       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4858       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4859       tmp->translate(vec);
4860       double tmp3[2],radius,alpha,alpha0;
4861       const double *p0=i+1<nbOfLevsInVec?begin:third;
4862       const double *p1=i+1<nbOfLevsInVec?end:begin;
4863       const double *p2=i+1<nbOfLevsInVec?third:end;
4864       double vecPlane[3]={
4865         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4866         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4867         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4868       };
4869       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4870       if(norm>1.e-7)
4871         {
4872           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4873           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4874           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4875           double s2=norm2;
4876           double c2=cos(asin(s2));
4877           double m[3][3]={
4878             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4879             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4880             {-vec2[1]*s2, vec2[0]*s2, c2}
4881           };
4882           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]};
4883           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]};
4884           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]};
4885           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4886           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]);
4887           double angle=acos(cosangle/(radius*radius));
4888           tmp->rotate(end,vecPlane,angle);
4889         }
4890       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4891     }
4892   return ret.retn();
4893 }
4894
4895 /*!
4896  * This method is private because not easy to use for end user. This method is const contrary to
4897  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4898  * the coords sorted slice by slice.
4899  * \param isQuad specifies presence of quadratic cells.
4900  */
4901 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4902 {
4903   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4904   int nbOf2DCells=getNumberOfCells();
4905   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4906   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4907   const int *conn=_nodal_connec->getConstPointer();
4908   const int *connI=_nodal_connec_index->getConstPointer();
4909   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4910   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4911   newConnI->alloc(nbOf3DCells+1,1);
4912   int *newConnIPtr=newConnI->getPointer();
4913   *newConnIPtr++=0;
4914   std::vector<int> newc;
4915   for(int j=0;j<nbOf2DCells;j++)
4916     {
4917       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4918       *newConnIPtr++=(int)newc.size();
4919     }
4920   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4921   int *newConnPtr=newConn->getPointer();
4922   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4923   newConnIPtr=newConnI->getPointer();
4924   for(int iz=0;iz<nbOf1DCells;iz++)
4925     {
4926       if(iz!=0)
4927         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4928       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4929         {
4930           int icell=(int)(iter-newc.begin());
4931           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4932             {
4933               if(*iter!=-1)
4934                 *newConnPtr=(*iter)+iz*deltaPerLev;
4935               else
4936                 *newConnPtr=-1;
4937             }
4938           else
4939             *newConnPtr=(*iter);
4940         }
4941     }
4942   ret->setConnectivity(newConn,newConnI,true);
4943   ret->setCoords(getCoords());
4944   return ret;
4945 }
4946
4947 /*!
4948  * Checks if \a this mesh is constituted by only quadratic cells.
4949  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4950  *  \throw If the coordinates array is not set.
4951  *  \throw If the nodal connectivity of cells is not defined.
4952  */
4953 bool MEDCouplingUMesh::isFullyQuadratic() const
4954 {
4955   checkFullyDefined();
4956   bool ret=true;
4957   int nbOfCells=getNumberOfCells();
4958   for(int i=0;i<nbOfCells && ret;i++)
4959     {
4960       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4961       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4962       ret=cm.isQuadratic();
4963     }
4964   return ret;
4965 }
4966
4967 /*!
4968  * Checks if \a this mesh includes any quadratic cell.
4969  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4970  *  \throw If the coordinates array is not set.
4971  *  \throw If the nodal connectivity of cells is not defined.
4972  */
4973 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4974 {
4975   checkFullyDefined();
4976   bool ret=false;
4977   int nbOfCells=getNumberOfCells();
4978   for(int i=0;i<nbOfCells && !ret;i++)
4979     {
4980       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4981       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4982       ret=cm.isQuadratic();
4983     }
4984   return ret;
4985 }
4986
4987 /*!
4988  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4989  * this mesh, it remains unchanged.
4990  *  \throw If the coordinates array is not set.
4991  *  \throw If the nodal connectivity of cells is not defined.
4992  */
4993 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4994 {
4995   checkFullyDefined();
4996   int nbOfCells=getNumberOfCells();
4997   int delta=0;
4998   const int *iciptr=_nodal_connec_index->getConstPointer();
4999   for(int i=0;i<nbOfCells;i++)
5000     {
5001       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5002       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5003       if(cm.isQuadratic())
5004         {
5005           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5006           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5007           if(!cml.isDynamic())
5008             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5009           else
5010             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5011         }
5012     }
5013   if(delta==0)
5014     return ;
5015   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5016   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5017   const int *icptr=_nodal_connec->getConstPointer();
5018   newConn->alloc(getMeshLength()-delta,1);
5019   newConnI->alloc(nbOfCells+1,1);
5020   int *ocptr=newConn->getPointer();
5021   int *ociptr=newConnI->getPointer();
5022   *ociptr=0;
5023   _types.clear();
5024   for(int i=0;i<nbOfCells;i++,ociptr++)
5025     {
5026       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5027       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5028       if(!cm.isQuadratic())
5029         {
5030           _types.insert(type);
5031           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5032           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5033         }
5034       else
5035         {
5036           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5037           _types.insert(typel);
5038           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5039           int newNbOfNodes=cml.getNumberOfNodes();
5040           if(cml.isDynamic())
5041             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5042           *ocptr++=(int)typel;
5043           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5044           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5045         }
5046     }
5047   setConnectivity(newConn,newConnI,false);
5048 }
5049
5050 /*!
5051  * This method converts all linear cell in \a this to quadratic one.
5052  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5053  * 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)
5054  * 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.
5055  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5056  * end of the existing coordinates.
5057  * 
5058  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5059  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5060  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5061  * 
5062  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5063  *
5064  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5065  */
5066 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5067 {
5068   DataArrayInt *conn=0,*connI=0;
5069   DataArrayDouble *coords=0;
5070   std::set<INTERP_KERNEL::NormalizedCellType> types;
5071   checkFullyDefined();
5072   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5073   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5074   int meshDim=getMeshDimension();
5075   switch(conversionType)
5076   {
5077     case 0:
5078       switch(meshDim)
5079       {
5080         case 1:
5081           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5082           connSafe=conn; connISafe=connI; coordsSafe=coords;
5083           break;
5084         case 2:
5085           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5086           connSafe=conn; connISafe=connI; coordsSafe=coords;
5087           break;
5088         case 3:
5089           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5090           connSafe=conn; connISafe=connI; coordsSafe=coords;
5091           break;
5092         default:
5093           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5094       }
5095       break;
5096         case 1:
5097           {
5098             switch(meshDim)
5099             {
5100               case 1:
5101                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5102                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5103                 break;
5104               case 2:
5105                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5106                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5107                 break;
5108               case 3:
5109                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5110                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5111                 break;
5112               default:
5113                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5114             }
5115             break;
5116           }
5117         default:
5118           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5119   }
5120   setConnectivity(connSafe,connISafe,false);
5121   _types=types;
5122   setCoords(coordsSafe);
5123   return ret.retn();
5124 }
5125
5126 #if 0
5127 /*!
5128  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5129  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5130  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5131  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5132  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5133  * This method can be seen as the opposite method of colinearize2D.
5134  * 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
5135  * to avoid to modify the numbering of existing nodes.
5136  *
5137  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5138  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5139  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5140  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5141  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5142  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5143  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5144  *
5145  * \sa buildDescendingConnectivity2
5146  */
5147 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5148                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5149 {
5150   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5151     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5152   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5153   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5154     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5155   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5156     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5157   //DataArrayInt *out0(0),*outi0(0);
5158   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5159   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5160   //out0s=out0s->buildUnique(); out0s->sort(true);
5161 }
5162 #endif
5163
5164 /*!
5165  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5166  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5167  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5168  */
5169 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5170 {
5171   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5172   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5174   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5175   int nbOfCells=getNumberOfCells();
5176   int nbOfNodes=getNumberOfNodes();
5177   const int *cPtr=_nodal_connec->getConstPointer();
5178   const int *icPtr=_nodal_connec_index->getConstPointer();
5179   int lastVal=0,offset=nbOfNodes;
5180   for(int i=0;i<nbOfCells;i++,icPtr++)
5181     {
5182       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5183       if(type==INTERP_KERNEL::NORM_SEG2)
5184         {
5185           types.insert(INTERP_KERNEL::NORM_SEG3);
5186           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5187           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5188           newConn->pushBackSilent(offset++);
5189           lastVal+=4;
5190           newConnI->pushBackSilent(lastVal);
5191           ret->pushBackSilent(i);
5192         }
5193       else
5194         {
5195           types.insert(type);
5196           lastVal+=(icPtr[1]-icPtr[0]);
5197           newConnI->pushBackSilent(lastVal);
5198           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5199         }
5200     }
5201   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5202   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5203   return ret.retn();
5204 }
5205
5206 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
5207 {
5208   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5210   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5211   //
5212   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5213   DataArrayInt *conn1D=0,*conn1DI=0;
5214   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5215   DataArrayDouble *coordsTmp=0;
5216   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5217   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5218   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5219   const int *c1DPtr=conn1D->begin();
5220   const int *c1DIPtr=conn1DI->begin();
5221   int nbOfCells=getNumberOfCells();
5222   const int *cPtr=_nodal_connec->getConstPointer();
5223   const int *icPtr=_nodal_connec_index->getConstPointer();
5224   int lastVal=0;
5225   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5226     {
5227       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5228       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5229       if(!cm.isQuadratic())
5230         {
5231           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5232           types.insert(typ2); newConn->pushBackSilent(typ2);
5233           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5234           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5235             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5236           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5237           newConnI->pushBackSilent(lastVal);
5238           ret->pushBackSilent(i);
5239         }
5240       else
5241         {
5242           types.insert(typ);
5243           lastVal+=(icPtr[1]-icPtr[0]);
5244           newConnI->pushBackSilent(lastVal);
5245           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5246         }
5247     }
5248   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5249   return ret.retn();
5250 }
5251
5252 /*!
5253  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5254  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5255  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5256  */
5257 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5258 {
5259   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5260   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5261   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5262 }
5263
5264 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5265 {
5266   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5267   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5268   //
5269   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5271   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5272   //
5273   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5274   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5275   DataArrayInt *conn1D=0,*conn1DI=0;
5276   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5277   DataArrayDouble *coordsTmp=0;
5278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5279   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5281   const int *c1DPtr=conn1D->begin();
5282   const int *c1DIPtr=conn1DI->begin();
5283   int nbOfCells=getNumberOfCells();
5284   const int *cPtr=_nodal_connec->getConstPointer();
5285   const int *icPtr=_nodal_connec_index->getConstPointer();
5286   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5287   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5288     {
5289       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5290       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5291       if(!cm.isQuadratic())
5292         {
5293           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5294           types.insert(typ2); newConn->pushBackSilent(typ2);
5295           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5296           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5297             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5298           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5299           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
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   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5312   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5313   return ret.retn();
5314 }
5315
5316 /*!
5317  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5318  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5319  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5320  */
5321 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5322 {
5323   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5324   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5325   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5326 }
5327
5328 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5329 {
5330   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5331   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5332   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5333   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5334   //
5335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5338   //
5339   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5340   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5341   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5342   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5343   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5345   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5346   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5348   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5349   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5350   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5351   int nbOfCells=getNumberOfCells();
5352   const int *cPtr=_nodal_connec->getConstPointer();
5353   const int *icPtr=_nodal_connec_index->getConstPointer();
5354   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5355   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5356     {
5357       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5358       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5359       if(!cm.isQuadratic())
5360         {
5361           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5362           if(typ2==INTERP_KERNEL::NORM_ERROR)
5363             {
5364               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5365               throw INTERP_KERNEL::Exception(oss.str().c_str());
5366             }
5367           types.insert(typ2); newConn->pushBackSilent(typ2);
5368           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5369           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5370             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5371           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5372             {
5373               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5374               int tmpPos=newConn->getNumberOfTuples();
5375               newConn->pushBackSilent(nodeId2);
5376               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5377             }
5378           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5379           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5380           newConnI->pushBackSilent(lastVal);
5381           ret->pushBackSilent(i);
5382         }
5383       else
5384         {
5385           types.insert(typ);
5386           lastVal+=(icPtr[1]-icPtr[0]);
5387           newConnI->pushBackSilent(lastVal);
5388           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5389         }
5390     }
5391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5393   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5394   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5395   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5396   int *c=newConn->getPointer();
5397   const int *cI(newConnI->begin());
5398   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5399     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5400   offset=coordsTmp2Safe->getNumberOfTuples();
5401   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5402     c[cI[(*elt)+1]-1]+=offset;
5403   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5404   return ret.retn();
5405 }
5406
5407 /*!
5408  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5409  * so that the number of cells remains the same. Quadratic faces are converted to
5410  * polygons. This method works only for 2D meshes in
5411  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5412  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5413  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5414  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5415  *         a polylinized edge constituting the input polygon.
5416  *  \throw If the coordinates array is not set.
5417  *  \throw If the nodal connectivity of cells is not defined.
5418  *  \throw If \a this->getMeshDimension() != 2.
5419  *  \throw If \a this->getSpaceDimension() != 2.
5420  */
5421 void MEDCouplingUMesh::tessellate2D(double eps)
5422 {
5423   checkFullyDefined();
5424   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5425     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5426   double epsa=fabs(eps);
5427   if(epsa<std::numeric_limits<double>::min())
5428     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 !");
5429   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5430   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5433   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5434   revDesc1=0; revDescIndx1=0;
5435   mDesc->tessellate2DCurve(eps);
5436   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5437   setCoords(mDesc->getCoords());
5438 }
5439
5440 /*!
5441  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5442  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5443  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5444  *         a sub-divided edge.
5445  *  \throw If the coordinates array is not set.
5446  *  \throw If the nodal connectivity of cells is not defined.
5447  *  \throw If \a this->getMeshDimension() != 1.
5448  *  \throw If \a this->getSpaceDimension() != 2.
5449  */
5450 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5451 {
5452   checkFullyDefined();
5453   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5454     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5455   double epsa=fabs(eps);
5456   if(epsa<std::numeric_limits<double>::min())
5457     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 !");
5458   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5459   int nbCells=getNumberOfCells();
5460   int nbNodes=getNumberOfNodes();
5461   const int *conn=_nodal_connec->getConstPointer();
5462   const int *connI=_nodal_connec_index->getConstPointer();
5463   const double *coords=_coords->getConstPointer();
5464   std::vector<double> addCoo;
5465   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5466   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5467   newConnI->alloc(nbCells+1,1);
5468   int *newConnIPtr=newConnI->getPointer();
5469   *newConnIPtr=0;
5470   int tmp1[3];
5471   INTERP_KERNEL::Node *tmp2[3];
5472   std::set<INTERP_KERNEL::NormalizedCellType> types;
5473   for(int i=0;i<nbCells;i++,newConnIPtr++)
5474     {
5475       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5476       if(cm.isQuadratic())
5477         {//assert(connI[i+1]-connI[i]-1==3)
5478           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5479           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5480           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5481           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5482           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5483           if(eac)
5484             {
5485               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5486               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5487               delete eac;
5488               newConnIPtr[1]=(int)newConn.size();
5489             }
5490           else
5491             {
5492               types.insert(INTERP_KERNEL::NORM_SEG2);
5493               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5494               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5495               newConnIPtr[1]=newConnIPtr[0]+3;
5496             }
5497         }
5498       else
5499         {
5500           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5501           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5502           newConnIPtr[1]=newConnIPtr[0]+3;
5503         }
5504     }
5505   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5506     return ;
5507   _types=types;
5508   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5509   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5510   newConnArr->alloc((int)newConn.size(),1);
5511   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5512   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5513   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5514   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5515   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5516   std::copy(addCoo.begin(),addCoo.end(),work);
5517   DataArrayDouble::SetArrayIn(newCoords,_coords);
5518   updateTime();
5519 }
5520
5521 /*!
5522  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5523  * In addition, returns an array mapping new cells to old ones. <br>
5524  * This method typically increases the number of cells in \a this mesh
5525  * but the number of nodes remains \b unchanged.
5526  * That's why the 3D splitting policies
5527  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5528  *  \param [in] policy - specifies a pattern used for splitting.
5529  * The semantic of \a policy is:
5530  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5531  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5532  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5533  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5534  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5535  *          an id of old cell producing it. The caller is to delete this array using
5536  *         decrRef() as it is no more needed. 
5537  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5538  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5539  *          and \a this->getMeshDimension() != 3. 
5540  *  \throw If \a policy is not one of the four discussed above.
5541  *  \throw If the nodal connectivity of cells is not defined.
5542  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5543  */
5544 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5545 {
5546   switch(policy)
5547   {
5548     case 0:
5549       return simplexizePol0();
5550     case 1:
5551       return simplexizePol1();
5552     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5553         return simplexizePlanarFace5();
5554     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5555         return simplexizePlanarFace6();
5556     default:
5557       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)");
5558   }
5559 }
5560
5561 /*!
5562  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5563  * - 1D: INTERP_KERNEL::NORM_SEG2
5564  * - 2D: INTERP_KERNEL::NORM_TRI3
5565  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5566  *
5567  * This method is useful for users that need to use P1 field services as
5568  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5569  * All these methods need mesh support containing only simplex cells.
5570  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5571  *  \throw If the coordinates array is not set.
5572  *  \throw If the nodal connectivity of cells is not defined.
5573  *  \throw If \a this->getMeshDimension() < 1.
5574  */
5575 bool MEDCouplingUMesh::areOnlySimplexCells() const
5576 {
5577   checkFullyDefined();
5578   int mdim=getMeshDimension();
5579   if(mdim<1 || mdim>3)
5580     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5581   int nbCells=getNumberOfCells();
5582   const int *conn=_nodal_connec->getConstPointer();
5583   const int *connI=_nodal_connec_index->getConstPointer();
5584   for(int i=0;i<nbCells;i++)
5585     {
5586       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5587       if(!cm.isSimplex())
5588         return false;
5589     }
5590   return true;
5591 }
5592
5593 /*!
5594  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5595  */
5596 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5597 {
5598   checkConnectivityFullyDefined();
5599   if(getMeshDimension()!=2)
5600     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5601   int nbOfCells=getNumberOfCells();
5602   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5603   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5604   ret->alloc(nbOfCells+nbOfCutCells,1);
5605   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5606   int *retPt=ret->getPointer();
5607   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5608   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5609   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5610   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5611   int *pt=newConn->getPointer();
5612   int *ptI=newConnI->getPointer();
5613   ptI[0]=0;
5614   const int *oldc=_nodal_connec->getConstPointer();
5615   const int *ci=_nodal_connec_index->getConstPointer();
5616   for(int i=0;i<nbOfCells;i++,ci++)
5617     {
5618       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5619         {
5620           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5621             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5622           pt=std::copy(tmp,tmp+8,pt);
5623           ptI[1]=ptI[0]+4;
5624           ptI[2]=ptI[0]+8;
5625           *retPt++=i;
5626           *retPt++=i;
5627           ptI+=2;
5628         }
5629       else
5630         {
5631           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5632           ptI[1]=ptI[0]+ci[1]-ci[0];
5633           ptI++;
5634           *retPt++=i;
5635         }
5636     }
5637   _nodal_connec->decrRef();
5638   _nodal_connec=newConn.retn();
5639   _nodal_connec_index->decrRef();
5640   _nodal_connec_index=newConnI.retn();
5641   computeTypes();
5642   updateTime();
5643   return ret.retn();
5644 }
5645
5646 /*!
5647  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5648  */
5649 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5650 {
5651   checkConnectivityFullyDefined();
5652   if(getMeshDimension()!=2)
5653     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5654   int nbOfCells=getNumberOfCells();
5655   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5656   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5657   ret->alloc(nbOfCells+nbOfCutCells,1);
5658   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5659   int *retPt=ret->getPointer();
5660   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5661   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5662   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5663   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5664   int *pt=newConn->getPointer();
5665   int *ptI=newConnI->getPointer();
5666   ptI[0]=0;
5667   const int *oldc=_nodal_connec->getConstPointer();
5668   const int *ci=_nodal_connec_index->getConstPointer();
5669   for(int i=0;i<nbOfCells;i++,ci++)
5670     {
5671       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5672         {
5673           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5674             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5675           pt=std::copy(tmp,tmp+8,pt);
5676           ptI[1]=ptI[0]+4;
5677           ptI[2]=ptI[0]+8;
5678           *retPt++=i;
5679           *retPt++=i;
5680           ptI+=2;
5681         }
5682       else
5683         {
5684           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5685           ptI[1]=ptI[0]+ci[1]-ci[0];
5686           ptI++;
5687           *retPt++=i;
5688         }
5689     }
5690   _nodal_connec->decrRef();
5691   _nodal_connec=newConn.retn();
5692   _nodal_connec_index->decrRef();
5693   _nodal_connec_index=newConnI.retn();
5694   computeTypes();
5695   updateTime();
5696   return ret.retn();
5697 }
5698
5699 /*!
5700  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5701  */
5702 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5703 {
5704   checkConnectivityFullyDefined();
5705   if(getMeshDimension()!=3)
5706     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5707   int nbOfCells=getNumberOfCells();
5708   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5709   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5710   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5711   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5712   int *retPt=ret->getPointer();
5713   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5714   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5715   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5716   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5717   int *pt=newConn->getPointer();
5718   int *ptI=newConnI->getPointer();
5719   ptI[0]=0;
5720   const int *oldc=_nodal_connec->getConstPointer();
5721   const int *ci=_nodal_connec_index->getConstPointer();
5722   for(int i=0;i<nbOfCells;i++,ci++)
5723     {
5724       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5725         {
5726           for(int j=0;j<5;j++,pt+=5,ptI++)
5727             {
5728               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5729               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];
5730               *retPt++=i;
5731               ptI[1]=ptI[0]+5;
5732             }
5733         }
5734       else
5735         {
5736           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5737           ptI[1]=ptI[0]+ci[1]-ci[0];
5738           ptI++;
5739           *retPt++=i;
5740         }
5741     }
5742   _nodal_connec->decrRef();
5743   _nodal_connec=newConn.retn();
5744   _nodal_connec_index->decrRef();
5745   _nodal_connec_index=newConnI.retn();
5746   computeTypes();
5747   updateTime();
5748   return ret.retn();
5749 }
5750
5751 /*!
5752  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5753  */
5754 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5755 {
5756   checkConnectivityFullyDefined();
5757   if(getMeshDimension()!=3)
5758     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5759   int nbOfCells=getNumberOfCells();
5760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5761   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5762   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5763   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5764   int *retPt=ret->getPointer();
5765   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5766   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5767   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5768   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5769   int *pt=newConn->getPointer();
5770   int *ptI=newConnI->getPointer();
5771   ptI[0]=0;
5772   const int *oldc=_nodal_connec->getConstPointer();
5773   const int *ci=_nodal_connec_index->getConstPointer();
5774   for(int i=0;i<nbOfCells;i++,ci++)
5775     {
5776       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5777         {
5778           for(int j=0;j<6;j++,pt+=5,ptI++)
5779             {
5780               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5781               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];
5782               *retPt++=i;
5783               ptI[1]=ptI[0]+5;
5784             }
5785         }
5786       else
5787         {
5788           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5789           ptI[1]=ptI[0]+ci[1]-ci[0];
5790           ptI++;
5791           *retPt++=i;
5792         }
5793     }
5794   _nodal_connec->decrRef();
5795   _nodal_connec=newConn.retn();
5796   _nodal_connec_index->decrRef();
5797   _nodal_connec_index=newConnI.retn();
5798   computeTypes();
5799   updateTime();
5800   return ret.retn();
5801 }
5802
5803 /*!
5804  * 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.
5805  * This method completly ignore coordinates.
5806  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5807  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5808  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5809  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5810  */
5811 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5812 {
5813   checkFullyDefined();
5814   if(getMeshDimension()!=2)
5815     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5816   int nbOfCells=getNumberOfCells();
5817   int *connI=_nodal_connec_index->getPointer();
5818   int newConnLgth=0;
5819   for(int i=0;i<nbOfCells;i++,connI++)
5820     {
5821       int offset=descIndex[i];
5822       int nbOfEdges=descIndex[i+1]-offset;
5823       //
5824       bool ddirect=desc[offset+nbOfEdges-1]>0;
5825       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5826       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5827       for(int j=0;j<nbOfEdges;j++)
5828         {
5829           bool direct=desc[offset+j]>0;
5830           int edgeId=std::abs(desc[offset+j])-1;
5831           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5832             {
5833               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5834               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5835               int ref2=direct?id1:id2;
5836               if(ref==ref2)
5837                 {
5838                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5839                   newConnLgth+=nbOfSubNodes-1;
5840                   ref=direct?id2:id1;
5841                 }
5842               else
5843                 {
5844                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5845                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5846                 }
5847             }
5848           else
5849             {
5850               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5851             }
5852         }
5853       newConnLgth++;//+1 is for cell type
5854       connI[1]=newConnLgth;
5855     }
5856   //
5857   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5858   newConn->alloc(newConnLgth,1);
5859   int *work=newConn->getPointer();
5860   for(int i=0;i<nbOfCells;i++)
5861     {
5862       *work++=INTERP_KERNEL::NORM_POLYGON;
5863       int offset=descIndex[i];
5864       int nbOfEdges=descIndex[i+1]-offset;
5865       for(int j=0;j<nbOfEdges;j++)
5866         {
5867           bool direct=desc[offset+j]>0;
5868           int edgeId=std::abs(desc[offset+j])-1;
5869           if(direct)
5870             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5871           else
5872             {
5873               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5874               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5875               work=std::copy(it,it+nbOfSubNodes-1,work);
5876             }
5877         }
5878     }
5879   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5880   _types.clear();
5881   if(nbOfCells>0)
5882     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5883 }
5884
5885 /*!
5886  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5887  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5888  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5889  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5890  * so it can be useful to call mergeNodes() before calling this method.
5891  *  \throw If \a this->getMeshDimension() <= 1.
5892  *  \throw If the coordinates array is not set.
5893  *  \throw If the nodal connectivity of cells is not defined.
5894  */
5895 void MEDCouplingUMesh::convertDegeneratedCells()
5896 {
5897   checkFullyDefined();
5898   if(getMeshDimension()<=1)
5899     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5900   int nbOfCells=getNumberOfCells();
5901   if(nbOfCells<1)
5902     return ;
5903   int initMeshLgth=getMeshLength();
5904   int *conn=_nodal_connec->getPointer();
5905   int *index=_nodal_connec_index->getPointer();
5906   int posOfCurCell=0;
5907   int newPos=0;
5908   int lgthOfCurCell;
5909   for(int i=0;i<nbOfCells;i++)
5910     {
5911       lgthOfCurCell=index[i+1]-posOfCurCell;
5912       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5913       int newLgth;
5914       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5915                                                                                                      conn+newPos+1,newLgth);
5916       conn[newPos]=newType;
5917       newPos+=newLgth+1;
5918       posOfCurCell=index[i+1];
5919       index[i+1]=newPos;
5920     }
5921   if(newPos!=initMeshLgth)
5922     _nodal_connec->reAlloc(newPos);
5923   computeTypes();
5924 }
5925
5926 /*!
5927  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5928  * A cell is considered to be oriented correctly if an angle between its
5929  * normal vector and a given vector is less than \c PI / \c 2.
5930  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5931  *         cells. 
5932  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5933  *         checked.
5934  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5935  *         is not cleared before filling in.
5936  *  \throw If \a this->getMeshDimension() != 2.
5937  *  \throw If \a this->getSpaceDimension() != 3.
5938  *
5939  *  \if ENABLE_EXAMPLES
5940  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5941  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5942  *  \endif
5943  */
5944 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5945 {
5946   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5947     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5948   int nbOfCells=getNumberOfCells();
5949   const int *conn=_nodal_connec->getConstPointer();
5950   const int *connI=_nodal_connec_index->getConstPointer();
5951   const double *coordsPtr=_coords->getConstPointer();
5952   for(int i=0;i<nbOfCells;i++)
5953     {
5954       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5955       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5956         {
5957           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5958           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5959             cells.push_back(i);
5960         }
5961     }
5962 }
5963
5964 /*!
5965  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5966  * considered to be oriented correctly if an angle between its normal vector and a
5967  * given vector is less than \c PI / \c 2. 
5968  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5969  *         cells. 
5970  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5971  *         checked.
5972  *  \throw If \a this->getMeshDimension() != 2.
5973  *  \throw If \a this->getSpaceDimension() != 3.
5974  *
5975  *  \if ENABLE_EXAMPLES
5976  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5977  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5978  *  \endif
5979  */
5980 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5981 {
5982   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5983     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5984   int nbOfCells=getNumberOfCells();
5985   int *conn=_nodal_connec->getPointer();
5986   const int *connI=_nodal_connec_index->getConstPointer();
5987   const double *coordsPtr=_coords->getConstPointer();
5988   bool isModified=false;
5989   for(int i=0;i<nbOfCells;i++)
5990     {
5991       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5992       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5993         {
5994           bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5995           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5996             {
5997               isModified=true;
5998               if(!isQuadratic)
5999                 {
6000                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
6001                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
6002                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
6003                 }
6004               else
6005                 {
6006                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
6007                   std::vector<int> tmp0(sz-1),tmp1(sz);
6008                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
6009                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
6010                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
6011                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
6012                 }
6013             }
6014         }
6015     }
6016   if(isModified)
6017     _nodal_connec->declareAsNew();
6018   updateTime();
6019 }
6020
6021 /*!
6022  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6023  * oriented facets. The normal vector of the facet should point out of the cell.
6024  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6025  *         is not cleared before filling in.
6026  *  \throw If \a this->getMeshDimension() != 3.
6027  *  \throw If \a this->getSpaceDimension() != 3.
6028  *  \throw If the coordinates array is not set.
6029  *  \throw If the nodal connectivity of cells is not defined.
6030  *
6031  *  \if ENABLE_EXAMPLES
6032  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6033  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6034  *  \endif
6035  */
6036 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6037 {
6038   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6039     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6040   int nbOfCells=getNumberOfCells();
6041   const int *conn=_nodal_connec->getConstPointer();
6042   const int *connI=_nodal_connec_index->getConstPointer();
6043   const double *coordsPtr=_coords->getConstPointer();
6044   for(int i=0;i<nbOfCells;i++)
6045     {
6046       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6047       if(type==INTERP_KERNEL::NORM_POLYHED)
6048         {
6049           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6050             cells.push_back(i);
6051         }
6052     }
6053 }
6054
6055 /*!
6056  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6057  * out of the cell. 
6058  *  \throw If \a this->getMeshDimension() != 3.
6059  *  \throw If \a this->getSpaceDimension() != 3.
6060  *  \throw If the coordinates array is not set.
6061  *  \throw If the nodal connectivity of cells is not defined.
6062  *  \throw If the reparation fails.
6063  *
6064  *  \if ENABLE_EXAMPLES
6065  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6066  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6067  *  \endif
6068  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6069  */
6070 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6071 {
6072   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6073     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6074   int nbOfCells=getNumberOfCells();
6075   int *conn=_nodal_connec->getPointer();
6076   const int *connI=_nodal_connec_index->getConstPointer();
6077   const double *coordsPtr=_coords->getConstPointer();
6078   for(int i=0;i<nbOfCells;i++)
6079     {
6080       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6081       if(type==INTERP_KERNEL::NORM_POLYHED)
6082         {
6083           try
6084           {
6085               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6086                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6087           }
6088           catch(INTERP_KERNEL::Exception& e)
6089           {
6090               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6091               throw INTERP_KERNEL::Exception(oss.str().c_str());
6092           }
6093         }
6094     }
6095   updateTime();
6096 }
6097
6098 /*!
6099  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6100  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6101  * according to which the first facet of the cell should be oriented to have the normal vector
6102  * pointing out of cell.
6103  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6104  *         cells. The caller is to delete this array using decrRef() as it is no more
6105  *         needed. 
6106  *  \throw If \a this->getMeshDimension() != 3.
6107  *  \throw If \a this->getSpaceDimension() != 3.
6108  *  \throw If the coordinates array is not set.
6109  *  \throw If the nodal connectivity of cells is not defined.
6110  *
6111  *  \if ENABLE_EXAMPLES
6112  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6113  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6114  *  \endif
6115  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6116  */
6117 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6118 {
6119   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6120   if(getMeshDimension()!=3)
6121     throw INTERP_KERNEL::Exception(msg);
6122   int spaceDim=getSpaceDimension();
6123   if(spaceDim!=3)
6124     throw INTERP_KERNEL::Exception(msg);
6125   //
6126   int nbOfCells=getNumberOfCells();
6127   int *conn=_nodal_connec->getPointer();
6128   const int *connI=_nodal_connec_index->getConstPointer();
6129   const double *coo=getCoords()->getConstPointer();
6130   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6131   for(int i=0;i<nbOfCells;i++)
6132     {
6133       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6134       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6135         {
6136           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6137             {
6138               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6139               cells->pushBackSilent(i);
6140             }
6141         }
6142     }
6143   return cells.retn();
6144 }
6145
6146 /*!
6147  * This method is a faster method to correct orientation of all 3D cells in \a this.
6148  * 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.
6149  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6150  * 
6151  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6152  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6153  */
6154 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6155 {
6156   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6157     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6158   int nbOfCells=getNumberOfCells();
6159   int *conn=_nodal_connec->getPointer();
6160   const int *connI=_nodal_connec_index->getConstPointer();
6161   const double *coordsPtr=_coords->getConstPointer();
6162   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6163   for(int i=0;i<nbOfCells;i++)
6164     {
6165       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6166       switch(type)
6167       {
6168         case INTERP_KERNEL::NORM_TETRA4:
6169           {
6170             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6171               {
6172                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6173                 ret->pushBackSilent(i);
6174               }
6175             break;
6176           }
6177         case INTERP_KERNEL::NORM_PYRA5:
6178           {
6179             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6180               {
6181                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6182                 ret->pushBackSilent(i);
6183               }
6184             break;
6185           }
6186         case INTERP_KERNEL::NORM_PENTA6:
6187         case INTERP_KERNEL::NORM_HEXA8:
6188         case INTERP_KERNEL::NORM_HEXGP12:
6189           {
6190             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6191               {
6192                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6193                 ret->pushBackSilent(i);
6194               }
6195             break;
6196           }
6197         case INTERP_KERNEL::NORM_POLYHED:
6198           {
6199             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6200               {
6201                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6202                 ret->pushBackSilent(i);
6203               }
6204             break;
6205           }
6206         default:
6207           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 !");
6208       }
6209     }
6210   updateTime();
6211   return ret.retn();
6212 }
6213
6214 /*!
6215  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6216  * If it is not the case an exception will be thrown.
6217  * This method is fast because the first cell of \a this is used to compute the plane.
6218  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6219  * \param pos output of size at least 3 used to store a point owned of searched plane.
6220  */
6221 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6222 {
6223   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6224     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6225   const int *conn=_nodal_connec->getConstPointer();
6226   const int *connI=_nodal_connec_index->getConstPointer();
6227   const double *coordsPtr=_coords->getConstPointer();
6228   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6229   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6230 }
6231
6232 /*!
6233  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6234  * cells. Currently cells of the following types are treated:
6235  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6236  * For a cell of other type an exception is thrown.
6237  * Space dimension of a 2D mesh can be either 2 or 3.
6238  * The Edge Ratio of a cell \f$t\f$ is: 
6239  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6240  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6241  *  the smallest edge lengths of \f$t\f$.
6242  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6243  *          cells and one time, lying on \a this mesh. The caller is to delete this
6244  *          field using decrRef() as it is no more needed. 
6245  *  \throw If the coordinates array is not set.
6246  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6247  *  \throw If the connectivity data array has more than one component.
6248  *  \throw If the connectivity data array has a named component.
6249  *  \throw If the connectivity index data array has more than one component.
6250  *  \throw If the connectivity index data array has a named component.
6251  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6252  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6253  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6254  */
6255 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6256 {
6257   checkCoherency();
6258   int spaceDim=getSpaceDimension();
6259   int meshDim=getMeshDimension();
6260   if(spaceDim!=2 && spaceDim!=3)
6261     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6262   if(meshDim!=2 && meshDim!=3)
6263     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6264   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6265   ret->setMesh(this);
6266   int nbOfCells=getNumberOfCells();
6267   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6268   arr->alloc(nbOfCells,1);
6269   double *pt=arr->getPointer();
6270   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6271   const int *conn=_nodal_connec->getConstPointer();
6272   const int *connI=_nodal_connec_index->getConstPointer();
6273   const double *coo=_coords->getConstPointer();
6274   double tmp[12];
6275   for(int i=0;i<nbOfCells;i++,pt++)
6276     {
6277       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6278       switch(t)
6279       {
6280         case INTERP_KERNEL::NORM_TRI3:
6281           {
6282             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6283             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6284             break;
6285           }
6286         case INTERP_KERNEL::NORM_QUAD4:
6287           {
6288             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6289             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6290             break;
6291           }
6292         case INTERP_KERNEL::NORM_TETRA4:
6293           {
6294             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6295             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6296             break;
6297           }
6298         default:
6299           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6300       }
6301       conn+=connI[i+1]-connI[i];
6302     }
6303   ret->setName("EdgeRatio");
6304   ret->synchronizeTimeWithSupport();
6305   return ret.retn();
6306 }
6307
6308 /*!
6309  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6310  * cells. Currently cells of the following types are treated:
6311  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6312  * For a cell of other type an exception is thrown.
6313  * Space dimension of a 2D mesh can be either 2 or 3.
6314  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6315  *          cells and one time, lying on \a this mesh. The caller is to delete this
6316  *          field using decrRef() as it is no more needed. 
6317  *  \throw If the coordinates array is not set.
6318  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6319  *  \throw If the connectivity data array has more than one component.
6320  *  \throw If the connectivity data array has a named component.
6321  *  \throw If the connectivity index data array has more than one component.
6322  *  \throw If the connectivity index data array has a named component.
6323  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6324  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6325  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6326  */
6327 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6328 {
6329   checkCoherency();
6330   int spaceDim=getSpaceDimension();
6331   int meshDim=getMeshDimension();
6332   if(spaceDim!=2 && spaceDim!=3)
6333     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6334   if(meshDim!=2 && meshDim!=3)
6335     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6336   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6337   ret->setMesh(this);
6338   int nbOfCells=getNumberOfCells();
6339   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6340   arr->alloc(nbOfCells,1);
6341   double *pt=arr->getPointer();
6342   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6343   const int *conn=_nodal_connec->getConstPointer();
6344   const int *connI=_nodal_connec_index->getConstPointer();
6345   const double *coo=_coords->getConstPointer();
6346   double tmp[12];
6347   for(int i=0;i<nbOfCells;i++,pt++)
6348     {
6349       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6350       switch(t)
6351       {
6352         case INTERP_KERNEL::NORM_TRI3:
6353           {
6354             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6355             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6356             break;
6357           }
6358         case INTERP_KERNEL::NORM_QUAD4:
6359           {
6360             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6361             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6362             break;
6363           }
6364         case INTERP_KERNEL::NORM_TETRA4:
6365           {
6366             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6367             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6368             break;
6369           }
6370         default:
6371           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6372       }
6373       conn+=connI[i+1]-connI[i];
6374     }
6375   ret->setName("AspectRatio");
6376   ret->synchronizeTimeWithSupport();
6377   return ret.retn();
6378 }
6379
6380 /*!
6381  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6382  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6383  * treated: INTERP_KERNEL::NORM_QUAD4.
6384  * For a cell of other type an exception is thrown.
6385  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6386  *          cells and one time, lying on \a this mesh. The caller is to delete this
6387  *          field using decrRef() as it is no more needed. 
6388  *  \throw If the coordinates array is not set.
6389  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6390  *  \throw If the connectivity data array has more than one component.
6391  *  \throw If the connectivity data array has a named component.
6392  *  \throw If the connectivity index data array has more than one component.
6393  *  \throw If the connectivity index data array has a named component.
6394  *  \throw If \a this->getMeshDimension() != 2.
6395  *  \throw If \a this->getSpaceDimension() != 3.
6396  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6397  */
6398 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6399 {
6400   checkCoherency();
6401   int spaceDim=getSpaceDimension();
6402   int meshDim=getMeshDimension();
6403   if(spaceDim!=3)
6404     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6405   if(meshDim!=2)
6406     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6407   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6408   ret->setMesh(this);
6409   int nbOfCells=getNumberOfCells();
6410   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6411   arr->alloc(nbOfCells,1);
6412   double *pt=arr->getPointer();
6413   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6414   const int *conn=_nodal_connec->getConstPointer();
6415   const int *connI=_nodal_connec_index->getConstPointer();
6416   const double *coo=_coords->getConstPointer();
6417   double tmp[12];
6418   for(int i=0;i<nbOfCells;i++,pt++)
6419     {
6420       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6421       switch(t)
6422       {
6423         case INTERP_KERNEL::NORM_QUAD4:
6424           {
6425             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6426             *pt=INTERP_KERNEL::quadWarp(tmp);
6427             break;
6428           }
6429         default:
6430           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6431       }
6432       conn+=connI[i+1]-connI[i];
6433     }
6434   ret->setName("Warp");
6435   ret->synchronizeTimeWithSupport();
6436   return ret.retn();
6437 }
6438
6439
6440 /*!
6441  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6442  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6443  * treated: INTERP_KERNEL::NORM_QUAD4.
6444  * For a cell of other type an exception is thrown.
6445  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6446  *          cells and one time, lying on \a this mesh. The caller is to delete this
6447  *          field using decrRef() as it is no more needed. 
6448  *  \throw If the coordinates array is not set.
6449  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6450  *  \throw If the connectivity data array has more than one component.
6451  *  \throw If the connectivity data array has a named component.
6452  *  \throw If the connectivity index data array has more than one component.
6453  *  \throw If the connectivity index data array has a named component.
6454  *  \throw If \a this->getMeshDimension() != 2.
6455  *  \throw If \a this->getSpaceDimension() != 3.
6456  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6457  */
6458 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6459 {
6460   checkCoherency();
6461   int spaceDim=getSpaceDimension();
6462   int meshDim=getMeshDimension();
6463   if(spaceDim!=3)
6464     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6465   if(meshDim!=2)
6466     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6467   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6468   ret->setMesh(this);
6469   int nbOfCells=getNumberOfCells();
6470   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6471   arr->alloc(nbOfCells,1);
6472   double *pt=arr->getPointer();
6473   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6474   const int *conn=_nodal_connec->getConstPointer();
6475   const int *connI=_nodal_connec_index->getConstPointer();
6476   const double *coo=_coords->getConstPointer();
6477   double tmp[12];
6478   for(int i=0;i<nbOfCells;i++,pt++)
6479     {
6480       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6481       switch(t)
6482       {
6483         case INTERP_KERNEL::NORM_QUAD4:
6484           {
6485             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6486             *pt=INTERP_KERNEL::quadSkew(tmp);
6487             break;
6488           }
6489         default:
6490           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6491       }
6492       conn+=connI[i+1]-connI[i];
6493     }
6494   ret->setName("Skew");
6495   ret->synchronizeTimeWithSupport();
6496   return ret.retn();
6497 }
6498
6499 /*!
6500  * This method aggregate the bbox of each cell and put it into bbox parameter.
6501  * 
6502  * \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)
6503  *                         For all other cases this input parameter is ignored.
6504  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6505  * 
6506  * \throw If \a this is not fully set (coordinates and connectivity).
6507  * \throw If a cell in \a this has no valid nodeId.
6508  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6509  */
6510 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6511 {
6512   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6513   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.
6514     return getBoundingBoxForBBTreeFast();
6515   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6516     {
6517       bool presenceOfQuadratic(false);
6518       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6519         {
6520           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6521           if(cm.isQuadratic())
6522             presenceOfQuadratic=true;
6523         }
6524       if(!presenceOfQuadratic)
6525         return getBoundingBoxForBBTreeFast();
6526       if(mDim==2 && sDim==2)
6527         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6528       else
6529         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6530     }
6531   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) !");
6532 }
6533
6534 /*!
6535  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6536  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6537  * 
6538  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6539  * 
6540  * \throw If \a this is not fully set (coordinates and connectivity).
6541  * \throw If a cell in \a this has no valid nodeId.
6542  */
6543 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6544 {
6545   checkFullyDefined();
6546   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6547   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6548   double *bbox(ret->getPointer());
6549   for(int i=0;i<nbOfCells*spaceDim;i++)
6550     {
6551       bbox[2*i]=std::numeric_limits<double>::max();
6552       bbox[2*i+1]=-std::numeric_limits<double>::max();
6553     }
6554   const double *coordsPtr(_coords->getConstPointer());
6555   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6556   for(int i=0;i<nbOfCells;i++)
6557     {
6558       int offset=connI[i]+1;
6559       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6560       for(int j=0;j<nbOfNodesForCell;j++)
6561         {
6562           int nodeId=conn[offset+j];
6563           if(nodeId>=0 && nodeId<nbOfNodes)
6564             {
6565               for(int k=0;k<spaceDim;k++)
6566                 {
6567                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6568                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6569                 }
6570               kk++;
6571             }
6572         }
6573       if(kk==0)
6574         {
6575           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6576           throw INTERP_KERNEL::Exception(oss.str().c_str());
6577         }
6578     }
6579   return ret.retn();
6580 }
6581
6582 /*!
6583  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6584  * useful for 2D meshes having quadratic cells
6585  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6586  * the two extremities of the arc of circle).
6587  * 
6588  * \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)
6589  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6590  * \throw If \a this is not fully defined.
6591  * \throw If \a this is not a mesh with meshDimension equal to 2.
6592  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6593  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6594  */
6595 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6596 {
6597   checkFullyDefined();
6598   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6599   if(spaceDim!=2 || mDim!=2)
6600     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!");
6601   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6602   double *bbox(ret->getPointer());
6603   const double *coords(_coords->getConstPointer());
6604   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6605   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6606     {
6607       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6608       int sz(connI[1]-connI[0]-1);
6609       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6610       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6611       INTERP_KERNEL::QuadraticPolygon *pol(0);
6612       for(int j=0;j<sz;j++)
6613         {
6614           int nodeId(conn[*connI+1+j]);
6615           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6616         }
6617       if(!cm.isQuadratic())
6618         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6619       else
6620         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6621       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6622       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6623     }
6624   return ret.retn();
6625 }
6626
6627 /*!
6628  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6629  * useful for 2D meshes having quadratic cells
6630  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6631  * the two extremities of the arc of circle).
6632  * 
6633  * \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)
6634  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6635  * \throw If \a this is not fully defined.
6636  * \throw If \a this is not a mesh with meshDimension equal to 1.
6637  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6638  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6639  */
6640 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6641 {
6642   checkFullyDefined();
6643   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6644   if(spaceDim!=2 || mDim!=1)
6645     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!");
6646   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6647   double *bbox(ret->getPointer());
6648   const double *coords(_coords->getConstPointer());
6649   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6650   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6651     {
6652       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6653       int sz(connI[1]-connI[0]-1);
6654       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6655       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6656       INTERP_KERNEL::Edge *edge(0);
6657       for(int j=0;j<sz;j++)
6658         {
6659           int nodeId(conn[*connI+1+j]);
6660           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6661         }
6662       if(!cm.isQuadratic())
6663         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6664       else
6665         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6666       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6667       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6668     }
6669   return ret.retn();
6670 }
6671
6672 /// @cond INTERNAL
6673
6674 namespace ParaMEDMEMImpl
6675 {
6676   class ConnReader
6677   {
6678   public:
6679     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6680     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6681   private:
6682     const int *_conn;
6683     int _val;
6684   };
6685
6686   class ConnReader2
6687   {
6688   public:
6689     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6690     bool operator() (const int& pos) { return _conn[pos]==_val; }
6691   private:
6692     const int *_conn;
6693     int _val;
6694   };
6695 }
6696
6697 /// @endcond
6698
6699 /*!
6700  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6701  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6702  * \a this is composed in cell types.
6703  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6704  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6705  * This parameter is kept only for compatibility with other methode listed above.
6706  */
6707 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6708 {
6709   checkConnectivityFullyDefined();
6710   const int *conn=_nodal_connec->getConstPointer();
6711   const int *connI=_nodal_connec_index->getConstPointer();
6712   const int *work=connI;
6713   int nbOfCells=getNumberOfCells();
6714   std::size_t n=getAllGeoTypes().size();
6715   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6716   std::set<INTERP_KERNEL::NormalizedCellType> types;
6717   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6718     {
6719       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6720       if(types.find(typ)!=types.end())
6721         {
6722           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6723           oss << " is not contiguous !";
6724           throw INTERP_KERNEL::Exception(oss.str().c_str());
6725         }
6726       types.insert(typ);
6727       ret[3*i]=typ;
6728       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6729       ret[3*i+1]=(int)std::distance(work,work2);
6730       work=work2;
6731     }
6732   return ret;
6733 }
6734
6735 /*!
6736  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6737  * only for types cell, type node is not managed.
6738  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6739  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6740  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6741  * If 2 or more same geometric type is in \a code and exception is thrown too.
6742  *
6743  * This method firstly checks
6744  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6745  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6746  * an exception is thrown too.
6747  * 
6748  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6749  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6750  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6751  */
6752 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6753 {
6754   if(code.empty())
6755     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6756   std::size_t sz=code.size();
6757   std::size_t n=sz/3;
6758   if(sz%3!=0)
6759     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6760   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6761   int nb=0;
6762   bool isNoPflUsed=true;
6763   for(std::size_t i=0;i<n;i++)
6764     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6765       {
6766         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6767         nb+=code[3*i+1];
6768         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6769           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6770         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6771       }
6772   if(types.size()!=n)
6773     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6774   if(isNoPflUsed)
6775     {
6776       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6777         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6778       if(types.size()==_types.size())
6779         return 0;
6780     }
6781   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6782   ret->alloc(nb,1);
6783   int *retPtr=ret->getPointer();
6784   const int *connI=_nodal_connec_index->getConstPointer();
6785   const int *conn=_nodal_connec->getConstPointer();
6786   int nbOfCells=getNumberOfCells();
6787   const int *i=connI;
6788   int kk=0;
6789   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6790     {
6791       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6792       int offset=(int)std::distance(connI,i);
6793       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6794       int nbOfCellsOfCurType=(int)std::distance(i,j);
6795       if(code[3*kk+2]==-1)
6796         for(int k=0;k<nbOfCellsOfCurType;k++)
6797           *retPtr++=k+offset;
6798       else
6799         {
6800           int idInIdsPerType=code[3*kk+2];
6801           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6802             {
6803               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6804               if(zePfl)
6805                 {
6806                   zePfl->checkAllocated();
6807                   if(zePfl->getNumberOfComponents()==1)
6808                     {
6809                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6810                         {
6811                           if(*k>=0 && *k<nbOfCellsOfCurType)
6812                             *retPtr=(*k)+offset;
6813                           else
6814                             {
6815                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6816                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6817                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6818                             }
6819                         }
6820                     }
6821                   else
6822                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6823                 }
6824               else
6825                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6826             }
6827           else
6828             {
6829               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6830               oss << " should be in [0," << idsPerType.size() << ") !";
6831               throw INTERP_KERNEL::Exception(oss.str().c_str());
6832             }
6833         }
6834       i=j;
6835     }
6836   return ret.retn();
6837 }
6838
6839 /*!
6840  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6841  * 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.
6842  * 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.
6843  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6844  * 
6845  * \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.
6846  * \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,
6847  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6848  * \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.
6849  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6850  * \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
6851  */
6852 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6853 {
6854   if(!profile)
6855     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6856   if(profile->getNumberOfComponents()!=1)
6857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6858   checkConnectivityFullyDefined();
6859   const int *conn=_nodal_connec->getConstPointer();
6860   const int *connI=_nodal_connec_index->getConstPointer();
6861   int nbOfCells=getNumberOfCells();
6862   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6863   std::vector<int> typeRangeVals(1);
6864   for(const int *i=connI;i!=connI+nbOfCells;)
6865     {
6866       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6867       if(std::find(types.begin(),types.end(),curType)!=types.end())
6868         {
6869           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6870         }
6871       types.push_back(curType);
6872       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6873       typeRangeVals.push_back((int)std::distance(connI,i));
6874     }
6875   //
6876   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6877   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6879   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6881   //
6882   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6883   code.resize(3*nbOfCastsFinal);
6884   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6885   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6886   for(int i=0;i<nbOfCastsFinal;i++)
6887     {
6888       int castId=castsPresent->getIJ(i,0);
6889       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6890       idsInPflPerType2.push_back(tmp3);
6891       code[3*i]=(int)types[castId];
6892       code[3*i+1]=tmp3->getNumberOfTuples();
6893       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6894       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6895         {
6896           tmp4->copyStringInfoFrom(*profile);
6897           idsPerType2.push_back(tmp4);
6898           code[3*i+2]=(int)idsPerType2.size()-1;
6899         }
6900       else
6901         {
6902           code[3*i+2]=-1;
6903         }
6904     }
6905   std::size_t sz2=idsInPflPerType2.size();
6906   idsInPflPerType.resize(sz2);
6907   for(std::size_t i=0;i<sz2;i++)
6908     {
6909       DataArrayInt *locDa=idsInPflPerType2[i];
6910       locDa->incrRef();
6911       idsInPflPerType[i]=locDa;
6912     }
6913   std::size_t sz=idsPerType2.size();
6914   idsPerType.resize(sz);
6915   for(std::size_t i=0;i<sz;i++)
6916     {
6917       DataArrayInt *locDa=idsPerType2[i];
6918       locDa->incrRef();
6919       idsPerType[i]=locDa;
6920     }
6921 }
6922
6923 /*!
6924  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6925  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6926  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6927  * 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.
6928  */
6929 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6930 {
6931   checkFullyDefined();
6932   nM1LevMesh->checkFullyDefined();
6933   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6934     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6935   if(_coords!=nM1LevMesh->getCoords())
6936     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6937   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6938   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6939   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6940   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6941   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6942   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6943   tmp->setConnectivity(tmp0,tmp1);
6944   tmp->renumberCells(ret0->getConstPointer(),false);
6945   revDesc=tmp->getNodalConnectivity();
6946   revDescIndx=tmp->getNodalConnectivityIndex();
6947   DataArrayInt *ret=0;
6948   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6949     {
6950       int tmp2;
6951       ret->getMaxValue(tmp2);
6952       ret->decrRef();
6953       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6954       throw INTERP_KERNEL::Exception(oss.str().c_str());
6955     }
6956   nM1LevMeshIds=ret;
6957   //
6958   revDesc->incrRef();
6959   revDescIndx->incrRef();
6960   ret1->incrRef();
6961   ret0->incrRef();
6962   meshnM1Old2New=ret0;
6963   return ret1;
6964 }
6965
6966 /*!
6967  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6968  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6969  * in "Old to New" mode.
6970  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6971  *          this array using decrRef() as it is no more needed.
6972  *  \throw If the nodal connectivity of cells is not defined.
6973  */
6974 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6975 {
6976   checkConnectivityFullyDefined();
6977   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6978   renumberCells(ret->getConstPointer(),false);
6979   return ret.retn();
6980 }
6981
6982 /*!
6983  * This methods checks that cells are sorted by their types.
6984  * This method makes asumption (no check) that connectivity is correctly set before calling.
6985  */
6986 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6987 {
6988   checkFullyDefined();
6989   const int *conn=_nodal_connec->getConstPointer();
6990   const int *connI=_nodal_connec_index->getConstPointer();
6991   int nbOfCells=getNumberOfCells();
6992   std::set<INTERP_KERNEL::NormalizedCellType> types;
6993   for(const int *i=connI;i!=connI+nbOfCells;)
6994     {
6995       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6996       if(types.find(curType)!=types.end())
6997         return false;
6998       types.insert(curType);
6999       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7000     }
7001   return true;
7002 }
7003
7004 /*!
7005  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7006  * The geometric type order is specified by MED file.
7007  * 
7008  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7009  */
7010 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7011 {
7012   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7013 }
7014
7015 /*!
7016  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7017  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7018  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7019  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7020  */
7021 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7022 {
7023   checkFullyDefined();
7024   const int *conn=_nodal_connec->getConstPointer();
7025   const int *connI=_nodal_connec_index->getConstPointer();
7026   int nbOfCells=getNumberOfCells();
7027   if(nbOfCells==0)
7028     return true;
7029   int lastPos=-1;
7030   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7031   for(const int *i=connI;i!=connI+nbOfCells;)
7032     {
7033       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7034       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7035       if(isTypeExists!=orderEnd)
7036         {
7037           int pos=(int)std::distance(orderBg,isTypeExists);
7038           if(pos<=lastPos)
7039             return false;
7040           lastPos=pos;
7041           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7042         }
7043       else
7044         {
7045           if(sg.find(curType)==sg.end())
7046             {
7047               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7048               sg.insert(curType);
7049             }
7050           else
7051             return false;
7052         }
7053     }
7054   return true;
7055 }
7056
7057 /*!
7058  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7059  * 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
7060  * 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'.
7061  */
7062 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7063 {
7064   checkConnectivityFullyDefined();
7065   int nbOfCells=getNumberOfCells();
7066   const int *conn=_nodal_connec->getConstPointer();
7067   const int *connI=_nodal_connec_index->getConstPointer();
7068   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7069   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7070   tmpa->alloc(nbOfCells,1);
7071   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7072   tmpb->fillWithZero();
7073   int *tmp=tmpa->getPointer();
7074   int *tmp2=tmpb->getPointer();
7075   for(const int *i=connI;i!=connI+nbOfCells;i++)
7076     {
7077       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7078       if(where!=orderEnd)
7079         {
7080           int pos=(int)std::distance(orderBg,where);
7081           tmp2[pos]++;
7082           tmp[std::distance(connI,i)]=pos;
7083         }
7084       else
7085         {
7086           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7087           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7088           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7089           throw INTERP_KERNEL::Exception(oss.str().c_str());
7090         }
7091     }
7092   nbPerType=tmpb.retn();
7093   return tmpa.retn();
7094 }
7095
7096 /*!
7097  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7098  *
7099  * \return a new object containing the old to new correspondance.
7100  *
7101  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7102  */
7103 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7104 {
7105   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7106 }
7107
7108 /*!
7109  * 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.
7110  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7111  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7112  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7113  */
7114 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7115 {
7116   DataArrayInt *nbPerType=0;
7117   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7118   nbPerType->decrRef();
7119   return tmpa->buildPermArrPerLevel();
7120 }
7121
7122 /*!
7123  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7124  * The number of cells remains unchanged after the call of this method.
7125  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7126  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7127  *
7128  * \return the array giving the correspondance old to new.
7129  */
7130 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7131 {
7132   checkFullyDefined();
7133   computeTypes();
7134   const int *conn=_nodal_connec->getConstPointer();
7135   const int *connI=_nodal_connec_index->getConstPointer();
7136   int nbOfCells=getNumberOfCells();
7137   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7138   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7139     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7140       {
7141         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7142         types.push_back(curType);
7143         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7144       }
7145   DataArrayInt *ret=DataArrayInt::New();
7146   ret->alloc(nbOfCells,1);
7147   int *retPtr=ret->getPointer();
7148   std::fill(retPtr,retPtr+nbOfCells,-1);
7149   int newCellId=0;
7150   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7151     {
7152       for(const int *i=connI;i!=connI+nbOfCells;i++)
7153         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7154           retPtr[std::distance(connI,i)]=newCellId++;
7155     }
7156   renumberCells(retPtr,false);
7157   return ret;
7158 }
7159
7160 /*!
7161  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7162  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7163  * This method makes asumption that connectivity is correctly set before calling.
7164  */
7165 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7166 {
7167   checkConnectivityFullyDefined();
7168   const int *conn=_nodal_connec->getConstPointer();
7169   const int *connI=_nodal_connec_index->getConstPointer();
7170   int nbOfCells=getNumberOfCells();
7171   std::vector<MEDCouplingUMesh *> ret;
7172   for(const int *i=connI;i!=connI+nbOfCells;)
7173     {
7174       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7175       int beginCellId=(int)std::distance(connI,i);
7176       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7177       int endCellId=(int)std::distance(connI,i);
7178       int sz=endCellId-beginCellId;
7179       int *cells=new int[sz];
7180       for(int j=0;j<sz;j++)
7181         cells[j]=beginCellId+j;
7182       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7183       delete [] cells;
7184       ret.push_back(m);
7185     }
7186   return ret;
7187 }
7188
7189 /*!
7190  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7191  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7192  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7193  *
7194  * \return a newly allocated instance, that the caller must manage.
7195  * \throw If \a this contains more than one geometric type.
7196  * \throw If the nodal connectivity of \a this is not fully defined.
7197  * \throw If the internal data is not coherent.
7198  */
7199 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7200 {
7201   checkConnectivityFullyDefined();
7202   if(_types.size()!=1)
7203     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7204   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7205   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7206   ret->setCoords(getCoords());
7207   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7208   if(retC)
7209     {
7210       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7211       retC->setNodalConnectivity(c);
7212     }
7213   else
7214     {
7215       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7216       if(!retD)
7217         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7218       DataArrayInt *c=0,*ci=0;
7219       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7220       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7221       retD->setNodalConnectivity(cs,cis);
7222     }
7223   return ret.retn();
7224 }
7225
7226 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7227 {
7228   checkConnectivityFullyDefined();
7229   if(_types.size()!=1)
7230     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7231   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7232   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7233   if(cm.isDynamic())
7234     {
7235       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7236       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7237       throw INTERP_KERNEL::Exception(oss.str().c_str());
7238     }
7239   int nbCells=getNumberOfCells();
7240   int typi=(int)typ;
7241   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7243   int *outPtr=connOut->getPointer();
7244   const int *conn=_nodal_connec->begin();
7245   const int *connI=_nodal_connec_index->begin();
7246   nbNodesPerCell++;
7247   for(int i=0;i<nbCells;i++,connI++)
7248     {
7249       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7250         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7251       else
7252         {
7253           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 << ") !";
7254           throw INTERP_KERNEL::Exception(oss.str().c_str());
7255         }
7256     }
7257   return connOut.retn();
7258 }
7259
7260 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7261 {
7262   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7263   checkConnectivityFullyDefined();
7264   if(_types.size()!=1)
7265     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7266   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7267   if(lgth<nbCells)
7268     throw INTERP_KERNEL::Exception(msg0);
7269   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7270   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7271   int *cp(c->getPointer()),*cip(ci->getPointer());
7272   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7273   cip[0]=0;
7274   for(int i=0;i<nbCells;i++,cip++,incip++)
7275     {
7276       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7277       int delta(stop-strt);
7278       if(delta>=1)
7279         {
7280           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7281             cp=std::copy(incp+strt,incp+stop,cp);
7282           else
7283             throw INTERP_KERNEL::Exception(msg0);
7284         }
7285       else
7286         throw INTERP_KERNEL::Exception(msg0);
7287       cip[1]=cip[0]+delta;
7288     }
7289   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7290 }
7291
7292 /*!
7293  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7294  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7295  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7296  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7297  * are not used here to avoid the build of big permutation array.
7298  *
7299  * \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
7300  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7301  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7302  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7303  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7304  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7305  * \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
7306  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7307  */
7308 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7309                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7310                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7311 {
7312   std::vector<const MEDCouplingUMesh *> ms2;
7313   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7314     if(*it)
7315       {
7316         (*it)->checkConnectivityFullyDefined();
7317         ms2.push_back(*it);
7318       }
7319   if(ms2.empty())
7320     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7321   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7322   int meshDim=ms2[0]->getMeshDimension();
7323   std::vector<const MEDCouplingUMesh *> m1ssm;
7324   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7325   //
7326   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7327   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7328   int fake=0,rk=0;
7329   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7330   ret1->alloc(0,1); ret2->alloc(0,1);
7331   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7332     {
7333       if(meshDim!=(*it)->getMeshDimension())
7334         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7335       if(refCoo!=(*it)->getCoords())
7336         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7337       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7338       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7339       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7340       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7341         {
7342           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7343           m1ssmSingleAuto.push_back(singleCell);
7344           m1ssmSingle.push_back(singleCell);
7345           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7346         }
7347     }
7348   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7349   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7350   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7351   for(std::size_t i=0;i<m1ssm.size();i++)
7352     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7353   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7354   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7355   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7356   return ret0.retn();
7357 }
7358
7359 /*!
7360  * This method returns a newly created DataArrayInt instance.
7361  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7362  */
7363 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7364 {
7365   checkFullyDefined();
7366   const int *conn=_nodal_connec->getConstPointer();
7367   const int *connIndex=_nodal_connec_index->getConstPointer();
7368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7369   for(const int *w=begin;w!=end;w++)
7370     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7371       ret->pushBackSilent(*w);
7372   return ret.retn();
7373 }
7374
7375 /*!
7376  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7377  * are in [0:getNumberOfCells())
7378  */
7379 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7380 {
7381   checkFullyDefined();
7382   const int *conn=_nodal_connec->getConstPointer();
7383   const int *connI=_nodal_connec_index->getConstPointer();
7384   int nbOfCells=getNumberOfCells();
7385   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7386   int *tmp=new int[nbOfCells];
7387   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7388     {
7389       int j=0;
7390       for(const int *i=connI;i!=connI+nbOfCells;i++)
7391         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7392           tmp[std::distance(connI,i)]=j++;
7393     }
7394   DataArrayInt *ret=DataArrayInt::New();
7395   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7396   ret->copyStringInfoFrom(*da);
7397   int *retPtr=ret->getPointer();
7398   const int *daPtr=da->getConstPointer();
7399   int nbOfElems=da->getNbOfElems();
7400   for(int k=0;k<nbOfElems;k++)
7401     retPtr[k]=tmp[daPtr[k]];
7402   delete [] tmp;
7403   return ret;
7404 }
7405
7406 /*!
7407  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7408  * This method \b works \b for mesh sorted by type.
7409  * cells whose ids is in 'idsPerGeoType' array.
7410  * This method conserves coords and name of mesh.
7411  */
7412 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7413 {
7414   std::vector<int> code=getDistributionOfTypes();
7415   std::size_t nOfTypesInThis=code.size()/3;
7416   int sz=0,szOfType=0;
7417   for(std::size_t i=0;i<nOfTypesInThis;i++)
7418     {
7419       if(code[3*i]!=type)
7420         sz+=code[3*i+1];
7421       else
7422         szOfType=code[3*i+1];
7423     }
7424   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7425     if(*work<0 || *work>=szOfType)
7426       {
7427         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7428         oss << ". It should be in [0," << szOfType << ") !";
7429         throw INTERP_KERNEL::Exception(oss.str().c_str());
7430       }
7431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7432   int *idsPtr=idsTokeep->getPointer();
7433   int offset=0;
7434   for(std::size_t i=0;i<nOfTypesInThis;i++)
7435     {
7436       if(code[3*i]!=type)
7437         for(int j=0;j<code[3*i+1];j++)
7438           *idsPtr++=offset+j;
7439       else
7440         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7441       offset+=code[3*i+1];
7442     }
7443   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7444   ret->copyTinyInfoFrom(this);
7445   return ret.retn();
7446 }
7447
7448 /*!
7449  * This method returns a vector of size 'this->getNumberOfCells()'.
7450  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7451  */
7452 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7453 {
7454   int ncell=getNumberOfCells();
7455   std::vector<bool> ret(ncell);
7456   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7457   const int *c=getNodalConnectivity()->getConstPointer();
7458   for(int i=0;i<ncell;i++)
7459     {
7460       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7461       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7462       ret[i]=cm.isQuadratic();
7463     }
7464   return ret;
7465 }
7466
7467 /*!
7468  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7469  */
7470 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7471 {
7472   if(other->getType()!=UNSTRUCTURED)
7473     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7474   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7475   return MergeUMeshes(this,otherC);
7476 }
7477
7478 /*!
7479  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7480  * computed by averaging coordinates of cell nodes, so this method is not a right
7481  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7482  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7483  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7484  *          components. The caller is to delete this array using decrRef() as it is
7485  *          no more needed.
7486  *  \throw If the coordinates array is not set.
7487  *  \throw If the nodal connectivity of cells is not defined.
7488  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7489  */
7490 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7491 {
7492   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7493   int spaceDim=getSpaceDimension();
7494   int nbOfCells=getNumberOfCells();
7495   ret->alloc(nbOfCells,spaceDim);
7496   ret->copyStringInfoFrom(*getCoords());
7497   double *ptToFill=ret->getPointer();
7498   const int *nodal=_nodal_connec->getConstPointer();
7499   const int *nodalI=_nodal_connec_index->getConstPointer();
7500   const double *coor=_coords->getConstPointer();
7501   for(int i=0;i<nbOfCells;i++)
7502     {
7503       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7504       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7505       ptToFill+=spaceDim;
7506     }
7507   return ret.retn();
7508 }
7509
7510 /*!
7511  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7512  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7513  * 
7514  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7515  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7516  * 
7517  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7518  * \throw If \a this is not fully defined (coordinates and connectivity)
7519  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7520  */
7521 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7522 {
7523   checkFullyDefined();
7524   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7525   int spaceDim=getSpaceDimension();
7526   int nbOfCells=getNumberOfCells();
7527   int nbOfNodes=getNumberOfNodes();
7528   ret->alloc(nbOfCells,spaceDim);
7529   double *ptToFill=ret->getPointer();
7530   const int *nodal=_nodal_connec->getConstPointer();
7531   const int *nodalI=_nodal_connec_index->getConstPointer();
7532   const double *coor=_coords->getConstPointer();
7533   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7534     {
7535       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7536       std::fill(ptToFill,ptToFill+spaceDim,0.);
7537       if(type!=INTERP_KERNEL::NORM_POLYHED)
7538         {
7539           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7540             {
7541               if(*conn>=0 && *conn<nbOfNodes)
7542                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7543               else
7544                 {
7545                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7546                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7547                 }
7548             }
7549           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7550           if(nbOfNodesInCell>0)
7551             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7552           else
7553             {
7554               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7555               throw INTERP_KERNEL::Exception(oss.str().c_str());
7556             }
7557         }
7558       else
7559         {
7560           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7561           s.erase(-1);
7562           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7563             {
7564               if(*it>=0 && *it<nbOfNodes)
7565                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7566               else
7567                 {
7568                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7569                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7570                 }
7571             }
7572           if(!s.empty())
7573             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7574           else
7575             {
7576               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7577               throw INTERP_KERNEL::Exception(oss.str().c_str());
7578             }
7579         }
7580     }
7581   return ret.retn();
7582 }
7583
7584 /*!
7585  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7586  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7587  * are specified via an array of cell ids. 
7588  *  \warning Validity of the specified cell ids is not checked! 
7589  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7590  *  \param [in] begin - an array of cell ids of interest.
7591  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7592  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7593  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7594  *          caller is to delete this array using decrRef() as it is no more needed. 
7595  *  \throw If the coordinates array is not set.
7596  *  \throw If the nodal connectivity of cells is not defined.
7597  *
7598  *  \if ENABLE_EXAMPLES
7599  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7600  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7601  *  \endif
7602  */
7603 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7604 {
7605   DataArrayDouble *ret=DataArrayDouble::New();
7606   int spaceDim=getSpaceDimension();
7607   int nbOfTuple=(int)std::distance(begin,end);
7608   ret->alloc(nbOfTuple,spaceDim);
7609   double *ptToFill=ret->getPointer();
7610   double *tmp=new double[spaceDim];
7611   const int *nodal=_nodal_connec->getConstPointer();
7612   const int *nodalI=_nodal_connec_index->getConstPointer();
7613   const double *coor=_coords->getConstPointer();
7614   for(const int *w=begin;w!=end;w++)
7615     {
7616       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7617       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7618       ptToFill+=spaceDim;
7619     }
7620   delete [] tmp;
7621   return ret;
7622 }
7623
7624 /*!
7625  * 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".
7626  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7627  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7628  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7629  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7630  * 
7631  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7632  * \throw If spaceDim!=3 or meshDim!=2.
7633  * \throw If connectivity of \a this is invalid.
7634  * \throw If connectivity of a cell in \a this points to an invalid node.
7635  */
7636 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7637 {
7638   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7639   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7640   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7641     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7642   ret->alloc(nbOfCells,4);
7643   double *retPtr(ret->getPointer());
7644   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7645   const double *coor(_coords->begin());
7646   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7647     {
7648       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7649       if(nodalI[1]-nodalI[0]>=3)
7650         {
7651           for(int j=0;j<3;j++)
7652             {
7653               int nodeId(nodal[nodalI[0]+1+j]);
7654               if(nodeId>=0 && nodeId<nbOfNodes)
7655                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7656               else
7657                 {
7658                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7659                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7660                 }
7661             }
7662         }
7663       else
7664         {
7665           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7666           throw INTERP_KERNEL::Exception(oss.str().c_str());
7667         }
7668       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7669       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7670     }
7671   return ret.retn();
7672 }
7673
7674 /*!
7675  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7676  * 
7677  */
7678 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7679 {
7680   if(!da)
7681     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7682   da->checkAllocated();
7683   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7684   ret->setCoords(da);
7685   int nbOfTuples=da->getNumberOfTuples();
7686   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7687   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7688   c->alloc(2*nbOfTuples,1);
7689   cI->alloc(nbOfTuples+1,1);
7690   int *cp=c->getPointer();
7691   int *cip=cI->getPointer();
7692   *cip++=0;
7693   for(int i=0;i<nbOfTuples;i++)
7694     {
7695       *cp++=INTERP_KERNEL::NORM_POINT1;
7696       *cp++=i;
7697       *cip++=2*(i+1);
7698     }
7699   ret->setConnectivity(c,cI,true);
7700   return ret.retn();
7701 }
7702 /*!
7703  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7704  * Cells and nodes of
7705  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7706  *  \param [in] mesh1 - the first mesh.
7707  *  \param [in] mesh2 - the second mesh.
7708  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7709  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7710  *          is no more needed.
7711  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7712  *  \throw If the coordinates array is not set in none of the meshes.
7713  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7714  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7715  */
7716 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7717 {
7718   std::vector<const MEDCouplingUMesh *> tmp(2);
7719   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7720   return MergeUMeshes(tmp);
7721 }
7722
7723 /*!
7724  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7725  * Cells and nodes of
7726  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7727  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7728  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7729  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7730  *          is no more needed.
7731  *  \throw If \a a.size() == 0.
7732  *  \throw If \a a[ *i* ] == NULL.
7733  *  \throw If the coordinates array is not set in none of the meshes.
7734  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7735  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7736  */
7737 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7738 {
7739   std::size_t sz=a.size();
7740   if(sz==0)
7741     return MergeUMeshesLL(a);
7742   for(std::size_t ii=0;ii<sz;ii++)
7743     if(!a[ii])
7744       {
7745         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7746         throw INTERP_KERNEL::Exception(oss.str().c_str());
7747       }
7748   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7749   std::vector< const MEDCouplingUMesh * > aa(sz);
7750   int spaceDim=-3;
7751   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7752     {
7753       const MEDCouplingUMesh *cur=a[i];
7754       const DataArrayDouble *coo=cur->getCoords();
7755       if(coo)
7756         spaceDim=coo->getNumberOfComponents();
7757     }
7758   if(spaceDim==-3)
7759     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7760   for(std::size_t i=0;i<sz;i++)
7761     {
7762       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7763       aa[i]=bb[i];
7764     }
7765   return MergeUMeshesLL(aa);
7766 }
7767
7768 /// @cond INTERNAL
7769
7770 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7771 {
7772   if(a.empty())
7773     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7774   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7775   int meshDim=(*it)->getMeshDimension();
7776   int nbOfCells=(*it)->getNumberOfCells();
7777   int meshLgth=(*it++)->getMeshLength();
7778   for(;it!=a.end();it++)
7779     {
7780       if(meshDim!=(*it)->getMeshDimension())
7781         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7782       nbOfCells+=(*it)->getNumberOfCells();
7783       meshLgth+=(*it)->getMeshLength();
7784     }
7785   std::vector<const MEDCouplingPointSet *> aps(a.size());
7786   std::copy(a.begin(),a.end(),aps.begin());
7787   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7788   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7789   ret->setCoords(pts);
7790   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7791   c->alloc(meshLgth,1);
7792   int *cPtr=c->getPointer();
7793   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7794   cI->alloc(nbOfCells+1,1);
7795   int *cIPtr=cI->getPointer();
7796   *cIPtr++=0;
7797   int offset=0;
7798   int offset2=0;
7799   for(it=a.begin();it!=a.end();it++)
7800     {
7801       int curNbOfCell=(*it)->getNumberOfCells();
7802       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7803       const int *curC=(*it)->_nodal_connec->getConstPointer();
7804       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7805       for(int j=0;j<curNbOfCell;j++)
7806         {
7807           const int *src=curC+curCI[j];
7808           *cPtr++=*src++;
7809           for(;src!=curC+curCI[j+1];src++,cPtr++)
7810             {
7811               if(*src!=-1)
7812                 *cPtr=*src+offset2;
7813               else
7814                 *cPtr=-1;
7815             }
7816         }
7817       offset+=curCI[curNbOfCell];
7818       offset2+=(*it)->getNumberOfNodes();
7819     }
7820   //
7821   ret->setConnectivity(c,cI,true);
7822   return ret.retn();
7823 }
7824
7825 /// @endcond
7826
7827 /*!
7828  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7829  * dimension and sharing the node coordinates array.
7830  * All cells of the first mesh precede all cells of the second mesh
7831  * within the result mesh. 
7832  *  \param [in] mesh1 - the first mesh.
7833  *  \param [in] mesh2 - the second mesh.
7834  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7835  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7836  *          is no more needed.
7837  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7838  *  \throw If the meshes do not share the node coordinates array.
7839  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7840  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7841  */
7842 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7843 {
7844   std::vector<const MEDCouplingUMesh *> tmp(2);
7845   tmp[0]=mesh1; tmp[1]=mesh2;
7846   return MergeUMeshesOnSameCoords(tmp);
7847 }
7848
7849 /*!
7850  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7851  * dimension and sharing the node coordinates array.
7852  * All cells of the *i*-th mesh precede all cells of the
7853  * (*i*+1)-th mesh within the result mesh.
7854  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7855  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7856  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7857  *          is no more needed.
7858  *  \throw If \a a.size() == 0.
7859  *  \throw If \a a[ *i* ] == NULL.
7860  *  \throw If the meshes do not share the node coordinates array.
7861  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7862  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7863  */
7864 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7865 {
7866   if(meshes.empty())
7867     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7868   for(std::size_t ii=0;ii<meshes.size();ii++)
7869     if(!meshes[ii])
7870       {
7871         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7872         throw INTERP_KERNEL::Exception(oss.str().c_str());
7873       }
7874   const DataArrayDouble *coords=meshes.front()->getCoords();
7875   int meshDim=meshes.front()->getMeshDimension();
7876   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7877   int meshLgth=0;
7878   int meshIndexLgth=0;
7879   for(;iter!=meshes.end();iter++)
7880     {
7881       if(coords!=(*iter)->getCoords())
7882         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7883       if(meshDim!=(*iter)->getMeshDimension())
7884         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7885       meshLgth+=(*iter)->getMeshLength();
7886       meshIndexLgth+=(*iter)->getNumberOfCells();
7887     }
7888   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7889   nodal->alloc(meshLgth,1);
7890   int *nodalPtr=nodal->getPointer();
7891   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7892   nodalIndex->alloc(meshIndexLgth+1,1);
7893   int *nodalIndexPtr=nodalIndex->getPointer();
7894   int offset=0;
7895   for(iter=meshes.begin();iter!=meshes.end();iter++)
7896     {
7897       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7898       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7899       int nbOfCells=(*iter)->getNumberOfCells();
7900       int meshLgth2=(*iter)->getMeshLength();
7901       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7902       if(iter!=meshes.begin())
7903         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7904       else
7905         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7906       offset+=meshLgth2;
7907     }
7908   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7909   ret->setName("merge");
7910   ret->setMeshDimension(meshDim);
7911   ret->setConnectivity(nodal,nodalIndex,true);
7912   ret->setCoords(coords);
7913   return ret;
7914 }
7915
7916 /*!
7917  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7918  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7919  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7920  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7921  * New" mode are returned for each input mesh.
7922  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7923  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7924  *          valid values [0,1,2], see zipConnectivityTraducer().
7925  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7926  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7927  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7928  *          no more needed.
7929  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7930  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7931  *          is no more needed.
7932  *  \throw If \a meshes.size() == 0.
7933  *  \throw If \a meshes[ *i* ] == NULL.
7934  *  \throw If the meshes do not share the node coordinates array.
7935  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7936  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7937  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7938  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7939  */
7940 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7941 {
7942   //All checks are delegated to MergeUMeshesOnSameCoords
7943   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7944   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7945   corr.resize(meshes.size());
7946   std::size_t nbOfMeshes=meshes.size();
7947   int offset=0;
7948   const int *o2nPtr=o2n->getConstPointer();
7949   for(std::size_t i=0;i<nbOfMeshes;i++)
7950     {
7951       DataArrayInt *tmp=DataArrayInt::New();
7952       int curNbOfCells=meshes[i]->getNumberOfCells();
7953       tmp->alloc(curNbOfCells,1);
7954       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7955       offset+=curNbOfCells;
7956       tmp->setName(meshes[i]->getName());
7957       corr[i]=tmp;
7958     }
7959   return ret.retn();
7960 }
7961
7962 /*!
7963  * Makes all given meshes share the nodal connectivity array. The common connectivity
7964  * array is created by concatenating the connectivity arrays of all given meshes. All
7965  * the given meshes must be of the same space dimension but dimension of cells **can
7966  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7967  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7968  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7969  *  \param [in,out] meshes - a vector of meshes to update.
7970  *  \throw If any of \a meshes is NULL.
7971  *  \throw If the coordinates array is not set in any of \a meshes.
7972  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7973  *  \throw If \a meshes are of different space dimension.
7974  */
7975 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7976 {
7977   std::size_t sz=meshes.size();
7978   if(sz==0 || sz==1)
7979     return;
7980   std::vector< const DataArrayDouble * > coords(meshes.size());
7981   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7982   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7983     {
7984       if((*it))
7985         {
7986           (*it)->checkConnectivityFullyDefined();
7987           const DataArrayDouble *coo=(*it)->getCoords();
7988           if(coo)
7989             *it2=coo;
7990           else
7991             {
7992               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7993               oss << " has no coordinate array defined !";
7994               throw INTERP_KERNEL::Exception(oss.str().c_str());
7995             }
7996         }
7997       else
7998         {
7999           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8000           oss << " is null !";
8001           throw INTERP_KERNEL::Exception(oss.str().c_str());
8002         }
8003     }
8004   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8005   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8006   int offset=(*it)->getNumberOfNodes();
8007   (*it++)->setCoords(res);
8008   for(;it!=meshes.end();it++)
8009     {
8010       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8011       (*it)->setCoords(res);
8012       (*it)->shiftNodeNumbersInConn(offset);
8013       offset+=oldNumberOfNodes;
8014     }
8015 }
8016
8017 /*!
8018  * Merges nodes coincident with a given precision within all given meshes that share
8019  * the nodal connectivity array. The given meshes **can be of different** mesh
8020  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8021  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8022  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8023  *  \param [in,out] meshes - a vector of meshes to update.
8024  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8025  *  \throw If any of \a meshes is NULL.
8026  *  \throw If the \a meshes do not share the same node coordinates array.
8027  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8028  */
8029 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8030 {
8031   if(meshes.empty())
8032     return ;
8033   std::set<const DataArrayDouble *> s;
8034   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8035     {
8036       if(*it)
8037         s.insert((*it)->getCoords());
8038       else
8039         {
8040           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 !";
8041           throw INTERP_KERNEL::Exception(oss.str().c_str());
8042         }
8043     }
8044   if(s.size()!=1)
8045     {
8046       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 !";
8047       throw INTERP_KERNEL::Exception(oss.str().c_str());
8048     }
8049   const DataArrayDouble *coo=*(s.begin());
8050   if(!coo)
8051     return;
8052   //
8053   DataArrayInt *comm,*commI;
8054   coo->findCommonTuples(eps,-1,comm,commI);
8055   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8056   int oldNbOfNodes=coo->getNumberOfTuples();
8057   int newNbOfNodes;
8058   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8059   if(oldNbOfNodes==newNbOfNodes)
8060     return ;
8061   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8062   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8063     {
8064       (*it)->renumberNodesInConn(o2n->getConstPointer());
8065       (*it)->setCoords(newCoords);
8066     } 
8067 }
8068
8069 /*!
8070  * 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.
8071  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8072  * \param isQuad specifies the policy of connectivity.
8073  * @ret in/out parameter in which the result will be append
8074  */
8075 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8076 {
8077   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8078   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8079   ret.push_back(cm.getExtrudedType());
8080   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8081   switch(flatType)
8082   {
8083     case INTERP_KERNEL::NORM_POINT1:
8084       {
8085         ret.push_back(connBg[1]);
8086         ret.push_back(connBg[1]+nbOfNodesPerLev);
8087         break;
8088       }
8089     case INTERP_KERNEL::NORM_SEG2:
8090       {
8091         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8092         ret.insert(ret.end(),conn,conn+4);
8093         break;
8094       }
8095     case INTERP_KERNEL::NORM_SEG3:
8096       {
8097         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8098         ret.insert(ret.end(),conn,conn+8);
8099         break;
8100       }
8101     case INTERP_KERNEL::NORM_QUAD4:
8102       {
8103         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8104         ret.insert(ret.end(),conn,conn+8);
8105         break;
8106       }
8107     case INTERP_KERNEL::NORM_TRI3:
8108       {
8109         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8110         ret.insert(ret.end(),conn,conn+6);
8111         break;
8112       }
8113     case INTERP_KERNEL::NORM_TRI6:
8114       {
8115         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,
8116           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8117         ret.insert(ret.end(),conn,conn+15);
8118         break;
8119       }
8120     case INTERP_KERNEL::NORM_QUAD8:
8121       {
8122         int conn[20]={
8123           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8124           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8125           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8126         };
8127         ret.insert(ret.end(),conn,conn+20);
8128         break;
8129       }
8130     case INTERP_KERNEL::NORM_POLYGON:
8131       {
8132         std::back_insert_iterator< std::vector<int> > ii(ret);
8133         std::copy(connBg+1,connEnd,ii);
8134         *ii++=-1;
8135         std::reverse_iterator<const int *> rConnBg(connEnd);
8136         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8137         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8138         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8139         for(std::size_t i=0;i<nbOfRadFaces;i++)
8140           {
8141             *ii++=-1;
8142             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8143             std::copy(conn,conn+4,ii);
8144           }
8145         break;
8146       }
8147     default:
8148       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8149   }
8150 }
8151
8152 /*!
8153  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8154  */
8155 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8156 {
8157   std::size_t i, ip1;
8158   double v[3]={0.,0.,0.};
8159   std::size_t sz=std::distance(begin,end);
8160   if(isQuadratic)
8161     sz/=2;
8162   for(i=0;i<sz;i++)
8163     {
8164       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];
8165       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8166       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8167     }
8168   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8169
8170   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8171   // SEG3 forming a circle):
8172   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8173     {
8174       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8175       for(std::size_t j=0;j<sz;j++)
8176         {
8177           if (j%2)  // current point i is quadratic, next point i+1 is standard
8178             {
8179               i = sz+j;
8180               ip1 = (j+1)%sz; // ip1 = "i+1"
8181             }
8182           else      // current point i is standard, next point i+1 is quadratic
8183             {
8184               i = j;
8185               ip1 = j+sz;
8186             }
8187           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8188           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8189           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8190         }
8191       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8192     }
8193   return (ret>0.);
8194 }
8195
8196 /*!
8197  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8198  */
8199 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8200 {
8201   std::vector<std::pair<int,int> > edges;
8202   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8203   const int *bgFace=begin;
8204   for(std::size_t i=0;i<nbOfFaces;i++)
8205     {
8206       const int *endFace=std::find(bgFace+1,end,-1);
8207       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8208       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8209         {
8210           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8211           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8212             return false;
8213           edges.push_back(p1);
8214         }
8215       bgFace=endFace+1;
8216     }
8217   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8218 }
8219
8220 /*!
8221  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8222  */
8223 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8224 {
8225   double vec0[3],vec1[3];
8226   std::size_t sz=std::distance(begin,end);
8227   if(sz%2!=0)
8228     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8229   int nbOfNodes=(int)sz/2;
8230   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8231   const double *pt0=coords+3*begin[0];
8232   const double *pt1=coords+3*begin[nbOfNodes];
8233   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8234   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8235 }
8236
8237 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8238 {
8239   std::size_t sz=std::distance(begin,end);
8240   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8241   std::size_t nbOfNodes(sz/2);
8242   std::copy(begin,end,(int *)tmp);
8243   for(std::size_t j=1;j<nbOfNodes;j++)
8244     {
8245       begin[j]=tmp[nbOfNodes-j];
8246       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8247     }
8248 }
8249
8250 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8251 {
8252   std::size_t sz=std::distance(begin,end);
8253   if(sz!=4)
8254     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8255   double vec0[3],vec1[3];
8256   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8257   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]; 
8258   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;
8259 }
8260
8261 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8262 {
8263   std::size_t sz=std::distance(begin,end);
8264   if(sz!=5)
8265     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8266   double vec0[3];
8267   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8268   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8269   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8270 }
8271
8272 /*!
8273  * 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 ) 
8274  * 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
8275  * a 2D space.
8276  *
8277  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8278  * \param [in] coords the coordinates with nb of components exactly equal to 3
8279  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8280  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8281  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8282  */
8283 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8284 {
8285   int nbFaces=std::count(begin+1,end,-1)+1;
8286   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8287   double *vPtr=v->getPointer();
8288   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8289   double *pPtr=p->getPointer();
8290   const int *stFaceConn=begin+1;
8291   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8292     {
8293       const int *endFaceConn=std::find(stFaceConn,end,-1);
8294       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8295       stFaceConn=endFaceConn+1;
8296     }
8297   pPtr=p->getPointer(); vPtr=v->getPointer();
8298   DataArrayInt *comm1=0,*commI1=0;
8299   v->findCommonTuples(eps,-1,comm1,commI1);
8300   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8301   const int *comm1Ptr=comm1->getConstPointer();
8302   const int *commI1Ptr=commI1->getConstPointer();
8303   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8304   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8305   //
8306   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8307   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8308   mm->finishInsertingCells();
8309   //
8310   for(int i=0;i<nbOfGrps1;i++)
8311     {
8312       int vecId=comm1Ptr[commI1Ptr[i]];
8313       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8314       DataArrayInt *comm2=0,*commI2=0;
8315       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8316       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8317       const int *comm2Ptr=comm2->getConstPointer();
8318       const int *commI2Ptr=commI2->getConstPointer();
8319       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8320       for(int j=0;j<nbOfGrps2;j++)
8321         {
8322           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8323             {
8324               res->insertAtTheEnd(begin,end);
8325               res->pushBackSilent(-1);
8326             }
8327           else
8328             {
8329               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8330               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8331               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8332               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8333               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8334               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8335               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8336               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8337               const int *idsNodePtr=idsNode->getConstPointer();
8338               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];
8339               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8340               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8341               if(std::abs(norm)>eps)
8342                 {
8343                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8344                   mm3->rotate(center,vec,angle);
8345                 }
8346               mm3->changeSpaceDimension(2);
8347               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8348               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8349               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8350               int nbOfCells=mm4->getNumberOfCells();
8351               for(int k=0;k<nbOfCells;k++)
8352                 {
8353                   int l=0;
8354                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8355                     res->pushBackSilent(idsNodePtr[*work]);
8356                   res->pushBackSilent(-1);
8357                 }
8358             }
8359         }
8360     }
8361   res->popBackSilent();
8362 }
8363
8364 /*!
8365  * 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
8366  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8367  * 
8368  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8369  * \param [in] coords coordinates expected to have 3 components.
8370  * \param [in] begin start of the nodal connectivity of the face.
8371  * \param [in] end end of the nodal connectivity (excluded) of the face.
8372  * \param [out] v the normalized vector of size 3
8373  * \param [out] p the pos of plane
8374  */
8375 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8376 {
8377   std::size_t nbPoints=std::distance(begin,end);
8378   if(nbPoints<3)
8379     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8380   double vec[3]={0.,0.,0.};
8381   std::size_t j=0;
8382   bool refFound=false;
8383   for(;j<nbPoints-1 && !refFound;j++)
8384     {
8385       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8386       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8387       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8388       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8389       if(norm>eps)
8390         {
8391           refFound=true;
8392           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8393         }
8394     }
8395   for(std::size_t i=j;i<nbPoints-1;i++)
8396     {
8397       double curVec[3];
8398       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8399       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8400       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8401       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8402       if(norm<eps)
8403         continue;
8404       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8405       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];
8406       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8407       if(norm>eps)
8408         {
8409           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8410           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8411           return ;
8412         }
8413     }
8414   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8415 }
8416
8417 /*!
8418  * This method tries to obtain a well oriented polyhedron.
8419  * If the algorithm fails, an exception will be thrown.
8420  */
8421 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8422 {
8423   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8424   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8425   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8426   isPerm[0]=true;
8427   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8428   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8429   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8430   //
8431   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8432     {
8433       bgFace=begin;
8434       std::size_t smthChanged=0;
8435       for(std::size_t i=0;i<nbOfFaces;i++)
8436         {
8437           endFace=std::find(bgFace+1,end,-1);
8438           nbOfEdgesInFace=std::distance(bgFace,endFace);
8439           if(!isPerm[i])
8440             {
8441               bool b;
8442               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8443                 {
8444                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8445                   std::pair<int,int> p2(p1.second,p1.first);
8446                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8447                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8448                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8449                 }
8450               if(isPerm[i])
8451                 { 
8452                   if(!b)
8453                     std::reverse(bgFace+1,endFace);
8454                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8455                     {
8456                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8457                       std::pair<int,int> p2(p1.second,p1.first);
8458                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8459                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8460                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8461                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8462                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8463                       if(it!=edgesOK.end())
8464                         {
8465                           edgesOK.erase(it);
8466                           edgesFinished.push_back(p1);
8467                         }
8468                       else
8469                         edgesOK.push_back(p1);
8470                     }
8471                 }
8472             }
8473           bgFace=endFace+1;
8474         }
8475       if(smthChanged==0)
8476         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8477     }
8478   if(!edgesOK.empty())
8479     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8480   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8481     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8482       bgFace=begin;
8483       for(std::size_t i=0;i<nbOfFaces;i++)
8484         {
8485           endFace=std::find(bgFace+1,end,-1);
8486           std::reverse(bgFace+1,endFace);
8487           bgFace=endFace+1;
8488         }
8489     }
8490 }
8491
8492 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8493 {
8494   int nbOfNodesExpected(skin->getNumberOfNodes());
8495   const int *n2oPtr(n2o->getConstPointer());
8496   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8497   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8498   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8499   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8500   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8501   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8502   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8503   if(nbOfNodesExpected<1)
8504     return ret.retn();
8505   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8506   *work++=n2oPtr[prevNode];
8507   for(int i=1;i<nbOfNodesExpected;i++)
8508     {
8509       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8510         {
8511           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8512           conn.erase(prevNode);
8513           if(conn.size()==1)
8514             {
8515               int curNode(*(conn.begin()));
8516               *work++=n2oPtr[curNode];
8517               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8518               shar.erase(prevCell);
8519               if(shar.size()==1)
8520                 {
8521                   prevCell=*(shar.begin());
8522                   prevNode=curNode;
8523                 }
8524               else
8525                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8526             }
8527           else
8528             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8529         }
8530       else
8531         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8532     }
8533   return ret.retn();
8534 }
8535
8536 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8537 {
8538   int nbOfNodesExpected(skin->getNumberOfNodes());
8539   int nbOfTurn(nbOfNodesExpected/2);
8540   const int *n2oPtr(n2o->getConstPointer());
8541   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8542   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8543   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8544   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8545   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8546   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8547   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8548   if(nbOfNodesExpected<1)
8549     return ret.retn();
8550   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8551   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8552   for(int i=1;i<nbOfTurn;i++)
8553     {
8554       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8555         {
8556           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8557           conn.erase(prevNode);
8558           if(conn.size()==1)
8559             {
8560               int curNode(*(conn.begin()));
8561               *work=n2oPtr[curNode];
8562               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8563               shar.erase(prevCell);
8564               if(shar.size()==1)
8565                 {
8566                   int curCell(*(shar.begin()));
8567                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8568                   prevCell=curCell;
8569                   prevNode=curNode;
8570                   work++;
8571                 }
8572               else
8573                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8574             }
8575           else
8576             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8577         }
8578       else
8579         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8580     }
8581   return ret.retn();
8582 }
8583
8584 /*!
8585  * This method makes the assumption spacedimension == meshdimension == 2.
8586  * This method works only for linear cells.
8587  * 
8588  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8589  */
8590 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8591 {
8592   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8593     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8594   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8595   int oldNbOfNodes(skin->getNumberOfNodes());
8596   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8597   int nbOfNodesExpected(skin->getNumberOfNodes());
8598   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8599   int nbCells(skin->getNumberOfCells());
8600   if(nbCells==nbOfNodesExpected)
8601     return buildUnionOf2DMeshLinear(skin,n2o);
8602   else if(2*nbCells==nbOfNodesExpected)
8603     return buildUnionOf2DMeshQuadratic(skin,n2o);
8604   else
8605     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8606 }
8607
8608 /*!
8609  * This method makes the assumption spacedimension == meshdimension == 3.
8610  * This method works only for linear cells.
8611  * 
8612  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8613  */
8614 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8615 {
8616   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8617     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8618   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8619   const int *conn=m->getNodalConnectivity()->getConstPointer();
8620   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8621   int nbOfCells=m->getNumberOfCells();
8622   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8623   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8624   if(nbOfCells<1)
8625     return ret.retn();
8626   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8627   for(int i=1;i<nbOfCells;i++)
8628     {
8629       *work++=-1;
8630       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8631     }
8632   return ret.retn();
8633 }
8634
8635 /*!
8636  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8637  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8638  */
8639 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8640 {
8641   double *w=zipFrmt;
8642   if(spaceDim==3)
8643     for(int i=0;i<nbOfNodesInCell;i++)
8644       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8645   else if(spaceDim==2)
8646     {
8647       for(int i=0;i<nbOfNodesInCell;i++)
8648         {
8649           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8650           *w++=0.;
8651         }
8652     }
8653   else
8654     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8655 }
8656
8657 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8658 {
8659   int nbOfCells=getNumberOfCells();
8660   if(nbOfCells<=0)
8661     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8662   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};
8663   ofs << "  <" << getVTKDataSetType() << ">\n";
8664   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8665   ofs << "      <PointData>\n" << pointData << std::endl;
8666   ofs << "      </PointData>\n";
8667   ofs << "      <CellData>\n" << cellData << std::endl;
8668   ofs << "      </CellData>\n";
8669   ofs << "      <Points>\n";
8670   if(getSpaceDimension()==3)
8671     _coords->writeVTK(ofs,8,"Points",byteData);
8672   else
8673     {
8674       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8675       coo->writeVTK(ofs,8,"Points",byteData);
8676     }
8677   ofs << "      </Points>\n";
8678   ofs << "      <Cells>\n";
8679   const int *cPtr=_nodal_connec->getConstPointer();
8680   const int *cIPtr=_nodal_connec_index->getConstPointer();
8681   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8682   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8683   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8684   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8685   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8686   int szFaceOffsets=0,szConn=0;
8687   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8688     {
8689       *w2=cPtr[cIPtr[i]];
8690       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8691         {
8692           *w1=-1;
8693           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8694           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8695         }
8696       else
8697         {
8698           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8699           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8700           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8701           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8702           w4=std::copy(c.begin(),c.end(),w4);
8703         }
8704     }
8705   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8706   types->writeVTK(ofs,8,"UInt8","types",byteData);
8707   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8708   if(szFaceOffsets!=0)
8709     {//presence of Polyhedra
8710       connectivity->reAlloc(szConn);
8711       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8712       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8713       w1=faces->getPointer();
8714       for(int i=0;i<nbOfCells;i++)
8715         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8716           {
8717             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8718             *w1++=nbFaces;
8719             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8720             for(int j=0;j<nbFaces;j++)
8721               {
8722                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8723                 *w1++=(int)std::distance(w6,w5);
8724                 w1=std::copy(w6,w5,w1);
8725                 w6=w5+1;
8726               }
8727           }
8728       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8729     }
8730   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8731   ofs << "      </Cells>\n";
8732   ofs << "    </Piece>\n";
8733   ofs << "  </" << getVTKDataSetType() << ">\n";
8734 }
8735
8736 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8737 {
8738   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8739   if(_mesh_dim==-2)
8740     { stream << " Not set !"; return ; }
8741   stream << " Mesh dimension : " << _mesh_dim << ".";
8742   if(_mesh_dim==-1)
8743     return ;
8744   if(!_coords)
8745     { stream << " No coordinates set !"; return ; }
8746   if(!_coords->isAllocated())
8747     { stream << " Coordinates set but not allocated !"; return ; }
8748   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8749   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8750   if(!_nodal_connec_index)
8751     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8752   if(!_nodal_connec_index->isAllocated())
8753     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8754   int lgth=_nodal_connec_index->getNumberOfTuples();
8755   int cpt=_nodal_connec_index->getNumberOfComponents();
8756   if(cpt!=1 || lgth<1)
8757     return ;
8758   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8759 }
8760
8761 std::string MEDCouplingUMesh::getVTKDataSetType() const
8762 {
8763   return std::string("UnstructuredGrid");
8764 }
8765
8766 std::string MEDCouplingUMesh::getVTKFileExtension() const
8767 {
8768   return std::string("vtu");
8769 }
8770
8771 /*!
8772  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8773  * returns a result mesh constituted by polygons.
8774  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8775  * all nodes from m2.
8776  * The meshes should be in 2D space. In
8777  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8778  * meshes.
8779  *  \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
8780  *                      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)
8781  *  \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
8782  *                      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)
8783  *  \param [in] eps - precision used to detect coincident mesh entities.
8784  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8785  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8786  *         this array using decrRef() as it is no more needed.
8787  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8788  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8789  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8790  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8791  *         it is no more needed.  
8792  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8793  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8794  *         is no more needed.  
8795  *  \throw If the coordinates array is not set in any of the meshes.
8796  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8797  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8798  *
8799  *  \sa conformize2D, mergeNodes
8800  */
8801 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8802                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8803 {
8804   if(!m1 || !m2)
8805     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8806   m1->checkFullyDefined();
8807   m2->checkFullyDefined();
8808   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8809     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8810
8811   // Step 1: compute all edge intersections (new nodes)
8812   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8813   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8814   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8815   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8816   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8817                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8818                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8819   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8821   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8822
8823   // Step 2: re-order newly created nodes according to the ordering found in m2
8824   std::vector< std::vector<int> > intersectEdge2;
8825   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8826   subDiv2.clear(); dd5=0; dd6=0;
8827
8828   // Step 3:
8829   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8830   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8831   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8832                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8833
8834   // Step 4: Prepare final result:
8835   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8836   addCooDa->alloc((int)(addCoo.size())/2,2);
8837   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8838   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8839   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8840   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8841   std::vector<const DataArrayDouble *> coordss(4);
8842   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8843   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8844   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8845   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8846   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8847   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8848   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8849   ret->setConnectivity(conn,connI,true);
8850   ret->setCoords(coo);
8851   cellNb1=c1.retn(); cellNb2=c2.retn();
8852   return ret.retn();
8853 }
8854
8855 /// @cond INTERNAL
8856
8857 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8858 {
8859   if(candidates.empty())
8860     return false;
8861   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8862     {
8863       const std::vector<int>& pool(intersectEdge1[*it]);
8864       int tmp[2]; tmp[0]=start; tmp[1]=stop;
8865       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8866         {
8867           retVal=*it+1;
8868           return true;
8869         }
8870       tmp[0]=stop; tmp[1]=start;
8871       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8872         {
8873           retVal=-*it-1;
8874           return true;
8875         }
8876     }
8877   return false;
8878 }
8879
8880 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,
8881                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8882 {
8883   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8884   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8885   int nCells(mesh1D->getNumberOfCells());
8886   if(nCells!=(int)intersectEdge2.size())
8887     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8888   const DataArrayDouble *coo2(mesh1D->getCoords());
8889   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8890   const double *coo2Ptr(coo2->begin());
8891   int offset1(coords1->getNumberOfTuples());
8892   int offset2(offset1+coo2->getNumberOfTuples());
8893   int offset3(offset2+addCoo.size()/2);
8894   std::vector<double> addCooQuad;
8895   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8896   int tmp[4],cicnt(0),kk(0);
8897   for(int i=0;i<nCells;i++)
8898     {
8899       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8900       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8901       const std::vector<int>& subEdges(intersectEdge2[i]);
8902       int nbSubEdge(subEdges.size()/2);
8903       for(int j=0;j<nbSubEdge;j++,kk++)
8904         {
8905           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));
8906           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8907           INTERP_KERNEL::Edge *e2Ptr(e2);
8908           std::map<int,int>::const_iterator itm;
8909           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8910             {
8911               tmp[0]=INTERP_KERNEL::NORM_SEG3;
8912               itm=mergedNodes.find(subEdges[2*j]);
8913               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8914               itm=mergedNodes.find(subEdges[2*j+1]);
8915               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8916               tmp[3]=offset3+(int)addCooQuad.size()/2;
8917               double tmp2[2];
8918               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8919               cicnt+=4;
8920               cOut->insertAtTheEnd(tmp,tmp+4);
8921               ciOut->pushBackSilent(cicnt);
8922             }
8923           else
8924             {
8925               tmp[0]=INTERP_KERNEL::NORM_SEG2;
8926               itm=mergedNodes.find(subEdges[2*j]);
8927               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8928               itm=mergedNodes.find(subEdges[2*j+1]);
8929               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8930               cicnt+=3;
8931               cOut->insertAtTheEnd(tmp,tmp+3);
8932               ciOut->pushBackSilent(cicnt);
8933             }
8934           int tmp00;
8935           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8936             {
8937               idsInRetColinear->pushBackSilent(kk);
8938               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8939             }
8940         }
8941       e->decrRef();
8942     }
8943   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8944   ret->setConnectivity(cOut,ciOut,true);
8945   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8946   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8947   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8948   std::vector<const DataArrayDouble *> coordss(4);
8949   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8950   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8951   ret->setCoords(arr);
8952   return ret.retn();
8953 }
8954
8955 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8956 {
8957   std::vector<int> allEdges;
8958   for(const int *it2(descBg);it2!=descEnd;it2++)
8959     {
8960       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
8961       if(*it2>0)
8962         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8963       else
8964         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8965     }
8966   std::size_t nb(allEdges.size());
8967   if(nb%2!=0)
8968     throw INTERP_KERNEL::Exception("BuildRefined2DCell : internal error 1 !");
8969   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8970   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8971   ret->setCoords(coords);
8972   ret->allocateCells(1);
8973   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
8974   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8975     connOut[kk]=allEdges[2*kk];
8976   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
8977   return ret.retn();
8978 }
8979
8980 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
8981 {
8982   bool isQuad(false);
8983   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
8984     {
8985       const INTERP_KERNEL::Edge *ee(*it);
8986       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
8987         isQuad=true;
8988     }
8989   if(!isQuad)
8990     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
8991   else
8992     {
8993       const double *coo(mesh2D->getCoords()->begin());
8994       std::size_t sz(conn.size());
8995       std::vector<double> addCoo;
8996       std::vector<int> conn2(conn);
8997       int offset(mesh2D->getNumberOfNodes());
8998       for(std::size_t i=0;i<sz;i++)
8999         {
9000           double tmp[2];
9001           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);
9002           addCoo.insert(addCoo.end(),tmp,tmp+2);
9003           conn2.push_back(offset+(int)i);
9004         }
9005       mesh2D->getCoords()->rearrange(1);
9006       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9007       mesh2D->getCoords()->rearrange(2);
9008       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9009     }
9010 }
9011
9012 /*!
9013  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9014  */
9015 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9016                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9017 {
9018   std::size_t nb(edge1Bis.size()/2);
9019   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9020   int iEnd(splitMesh1D->getNumberOfCells());
9021   if(iEnd==0)
9022     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9023   std::size_t ii,jj;
9024   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9025   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9026   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9027   //
9028   if(jj==nb)
9029     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9030       out0.resize(1); out1.resize(1);
9031       std::vector<int>& connOut(out0[0]);
9032       connOut.resize(nbOfEdgesOf2DCellSplit);
9033       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9034       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9035       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9036         {
9037           connOut[kk]=edge1Bis[2*kk];
9038           edgesPtr[kk]=edge1BisPtr[2*kk];
9039         }
9040     }
9041   else
9042     {
9043       // [i,iEnd[ contains the
9044       out0.resize(2); out1.resize(2);
9045       std::vector<int>& connOutLeft(out0[0]);
9046       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9047       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9048       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9049       for(std::size_t k=ii;k<jj+1;k++)
9050         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9051       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9052       for(int ik=iEnd-1;ik>=0;ik--)
9053         {
9054           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9055           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9056           ees[iEnd-1-ik]=ee;
9057         }
9058       for(int ik=iEnd-1;ik>=0;ik--)
9059         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9060       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9061         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9062       eleft.insert(eleft.end(),ees.begin(),ees.end());
9063       for(int ik=0;ik<iEnd;ik++)
9064         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9065       eright.insert(eright.end(),ees.rbegin(),ees.rend());
9066     }
9067 }
9068
9069 /// @endcond
9070
9071 /// @cond INTERNAL
9072
9073 struct CellInfo
9074 {
9075 public:
9076   CellInfo() { }
9077   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9078 public:
9079   std::vector<int> _edges;
9080   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9081 };
9082
9083 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9084 {
9085   std::size_t nbe(edges.size());
9086   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9087   for(std::size_t i=0;i<nbe;i++)
9088     {
9089       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9090       edgesPtr2[2*i]=edgesPtr[i]; edgesPtr2[2*i+1]=edgesPtr[i];
9091     }
9092   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9093   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9094   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9095 }
9096
9097 class EdgeInfo
9098 {
9099 public:
9100   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9101   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9102   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9103   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9104   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9105 private:
9106   int _istart;
9107   int _iend;
9108   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9109   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9110   int _left;
9111   int _right;
9112 };
9113
9114 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9115 {
9116   const MEDCouplingUMesh *mesh(_mesh);
9117   if(mesh)
9118     return ;
9119   if(_right<pos)
9120     return ;
9121   if(_left>pos)
9122     { _left++; _right++; return ; }
9123   if(_right==pos)
9124     {
9125       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9126       if((isLeft && isRight) || (!isLeft && !isRight))
9127         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9128       if(isLeft)
9129         return ;
9130       if(isRight)
9131         {
9132           _right++;
9133           return ;
9134         }
9135     }
9136   if(_left==pos)
9137     {
9138       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9139       if((isLeft && isRight) || (!isLeft && !isRight))
9140         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9141       if(isLeft)
9142         {
9143           _right++;
9144           return ;
9145         }
9146       if(isRight)
9147         {
9148           _left++;
9149           _right++;
9150           return ;
9151         }
9152     }
9153 }
9154
9155 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9156 {
9157   const MEDCouplingUMesh *mesh(_mesh);
9158   if(!mesh)
9159     {
9160       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9161     }
9162   else
9163     {// not fully splitting cell case
9164       if(mesh2D->getNumberOfCells()==1)
9165         {//little optimization. 1 cell no need to find in which cell mesh is !
9166           neighbors[0]=offset; neighbors[1]=offset;
9167           return;
9168         }
9169       else
9170         {
9171           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9172           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9173           if(cellId==-1)
9174             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9175           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9176         }
9177     }
9178 }
9179
9180 class VectorOfCellInfo
9181 {
9182 public:
9183   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9184   std::size_t size() const { return _pool.size(); }
9185   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9186   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);
9187   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9188   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9189   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9190   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9191 private:
9192   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9193   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9194   const CellInfo& get(int pos) const;
9195   CellInfo& get(int pos);
9196 private:
9197   std::vector<CellInfo> _pool;
9198   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9199   std::vector<EdgeInfo> _edge_info;
9200 };
9201
9202 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9203 {
9204   _pool[0]._edges=edges;
9205   _pool[0]._edges_ptr=edgesPtr;
9206 }
9207
9208 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9209 {
9210   if(_pool.empty())
9211     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9212   if(_pool.size()==1)
9213     return 0;
9214   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9215   if(!zeMesh)
9216     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9217   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9218   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9219 }
9220
9221 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)
9222 {
9223   get(pos);//to check pos
9224   bool isFast(pos==0 && _pool.size()==1);
9225   std::size_t sz(edges.size());
9226   // dealing with edges
9227   if(sz==1)
9228     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9229   else
9230     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9231   //
9232   std::vector<CellInfo> pool(_pool.size()-1+sz);
9233   for(int i=0;i<pos;i++)
9234     pool[i]=_pool[i];
9235   for(std::size_t j=0;j<sz;j++)
9236     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9237   for(int i=pos+1;i<(int)_pool.size();i++)
9238     pool[pos+sz-1]=_pool[i];
9239   _pool=pool;
9240   //
9241   if(sz==2)
9242     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9243   //
9244   if(isFast)
9245     {
9246       _ze_mesh=mesh;
9247       return ;
9248     }
9249   //
9250   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9251   if(pos>0)
9252     {
9253       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9254       ms.push_back(elt);
9255     }
9256   ms.push_back(mesh);
9257   if(pos<_ze_mesh->getNumberOfCells()-1)
9258   {
9259     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9260     ms.push_back(elt);
9261   }
9262   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9263   for(std::size_t j=0;j<ms2.size();j++)
9264     ms2[j]=ms[j];
9265   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9266 }
9267
9268 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9269 {
9270   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9271 }
9272
9273 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9274 {
9275   if(pos<0)
9276     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9277   int ret(0);
9278   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9279     {
9280       if((*it).isInMyRange(pos))
9281         return ret;
9282     }
9283   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9284 }
9285
9286 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9287 {
9288   get(pos);//to check;
9289   if(_edge_info.empty())
9290     return ;
9291   std::size_t sz(_edge_info.size()-1);
9292   for(std::size_t i=0;i<sz;i++)
9293     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9294 }
9295
9296 const CellInfo& VectorOfCellInfo::get(int pos) const
9297 {
9298   if(pos<0 || pos>=(int)_pool.size())
9299     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9300   return _pool[pos];
9301 }
9302
9303 CellInfo& VectorOfCellInfo::get(int pos)
9304 {
9305   if(pos<0 || pos>=(int)_pool.size())
9306     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9307   return _pool[pos];
9308 }
9309
9310 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9311                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9312 {
9313   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9314   if(nbCellsInSplitMesh1D==0)
9315     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9316   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9317   std::size_t nb(allEdges.size()),jj;
9318   if(nb%2!=0)
9319     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9320   std::vector<int> edge1Bis(nb*2);
9321   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9322   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9323   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9324   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9325   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9326   //
9327   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9328   int *idsLeftRightPtr(idsLeftRight->getPointer());
9329   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9330   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9331     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9332       int iEnd(iStart);
9333       for(;iEnd<nbCellsInSplitMesh1D;)
9334         {
9335           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9336           if(jj!=nb)
9337             break;
9338           else
9339             iEnd++;
9340         }
9341       if(iEnd<nbCellsInSplitMesh1D)
9342         iEnd++;
9343       //
9344       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9345       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9346       //
9347       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9348       retTmp->setCoords(splitMesh1D->getCoords());
9349       retTmp->allocateCells();
9350
9351       std::vector< std::vector<int> > out0;
9352       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9353
9354       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9355       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9356         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9357       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9358       //
9359       iStart=iEnd;
9360     }
9361   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9362     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9363   return pool.getZeMesh().retn();
9364 }
9365
9366 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9367                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9368                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9369 {
9370   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9371   //
9372   std::vector<int> allEdges;
9373   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr;
9374   for(const int *it(descBg);it!=descEnd;it++)
9375     {
9376       int edgeId(std::abs(*it)-1);
9377       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9378       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9379       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9380       if(*it>0)
9381         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9382       else
9383         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9384       std::size_t sz(edge1.size());
9385       for(std::size_t cnt=0;cnt<sz;cnt++)
9386         allEdgesPtr.push_back(ee);
9387     }
9388   //
9389   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9390 }
9391
9392 /// @endcond
9393
9394 /*!
9395  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9396  * 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
9397  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9398  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9399  *
9400  * \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
9401  *                      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)
9402  * \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
9403  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9404  * \param [in] eps - precision used to perform intersections and localization operations.
9405  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9406  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9407  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9408  *                               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.
9409  * \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
9410  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9411  *                               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.
9412  *
9413  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9414  */
9415 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9416 {
9417   if(!mesh2D || !mesh1D)
9418     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9419   mesh2D->checkFullyDefined();
9420   mesh1D->checkFullyDefined();
9421   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9422   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9423     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9424   // Step 1: compute all edge intersections (new nodes)
9425   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9426   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9427   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9428   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9429   //
9430   // Build desc connectivity
9431   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9433   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9434   std::map<int,int> mergedNodes;
9435   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9436   // use mergeNodes to fix intersectEdge1
9437   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9438     {
9439       std::size_t n((*it0).size()/2);
9440       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9441       std::map<int,int>::const_iterator it1;
9442       it1=mergedNodes.find(eltStart);
9443       if(it1!=mergedNodes.end())
9444         (*it0)[0]=(*it1).second;
9445       it1=mergedNodes.find(eltEnd);
9446       if(it1!=mergedNodes.end())
9447         (*it0)[2*n-1]=(*it1).second;
9448     }
9449   //
9450   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9451   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9452   // Step 2: re-order newly created nodes according to the ordering found in m2
9453   std::vector< std::vector<int> > intersectEdge2;
9454   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9455   subDiv2.clear();
9456   // Step 3: compute splitMesh1D
9457   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9459   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9460       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9461   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(-1); ret3->rearrange(2);
9462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9463   // deal with cells in mesh2D that are not cut but only some of their edges are
9464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9465   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9466   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9467   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
9468   if(!idsInDesc2DToBeRefined->empty())
9469     {
9470       DataArrayInt *out0(0),*outi0(0);
9471       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9472       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9473       out0s=out0;
9474       out0s=out0s->buildUnique();
9475       out0s->sort(true);
9476     }
9477   //
9478   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9479   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9480   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9481   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9482   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9483   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9484   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9485     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9486   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9487   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9488   if((DataArrayInt *)out0s)
9489     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9490   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9491   // OK all is ready to insert in ret2 mesh
9492   if(!untouchedCells->empty())
9493     {// the most easy part, cells in mesh2D not impacted at all
9494       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9495       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9496       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9497     }
9498   if((DataArrayInt *)out0s)
9499     {// here dealing with cells in out0s but not in cellsToBeModified
9500       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9501       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9502       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9503         {
9504           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9505         }
9506       int offset(ret2->getNumberOfTuples());
9507       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9508       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9509       partOfRet3->fillWithValue(-1); partOfRet3->rearrange(2);
9510       int kk(0),*ret3ptr(partOfRet3->getPointer());
9511       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9512         {
9513           int faceId(std::abs(*it)-1);
9514           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9515             {
9516               int tmp(fewModifiedCells->locateValue(*it2));
9517               if(tmp!=-1)
9518                 {
9519                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9520                     ret3ptr[2*kk]=tmp+offset;
9521                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9522                     ret3ptr[2*kk+1]=tmp+offset;
9523                 }
9524               else
9525                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : internal error 1 !");
9526             }
9527         }
9528       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9529     }
9530   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9531     {
9532       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9533       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9534       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9535       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9536       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9537       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));
9538       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9539       outMesh2DSplit.push_back(splitOfOneCell);
9540       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9541         ret2->pushBackSilent(*it);
9542     }
9543   //
9544   std::size_t nbOfMeshes(outMesh2DSplit.size());
9545   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9546   for(std::size_t i=0;i<nbOfMeshes;i++)
9547     tmp[i]=outMesh2DSplit[i];
9548   //
9549   ret1->getCoords()->setInfoOnComponents(compNames);
9550   //
9551   splitMesh1D=ret1.retn();
9552   splitMesh2D=MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp);
9553   cellIdInMesh2D=ret2.retn();
9554   cellIdInMesh1D=ret3.retn();
9555 }
9556
9557 /**
9558  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9559  * (newly created) nodes corresponding to the edge intersections.
9560  * Output params:
9561  * @param[out] cr, crI connectivity of the resulting mesh
9562  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9563  * TODO: describe input parameters
9564  */
9565 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9566                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9567                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9568                                                          const std::vector<double>& addCoords,
9569                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9570 {
9571   static const int SPACEDIM=2;
9572   const double *coo1(m1->getCoords()->getConstPointer());
9573   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9574   int offset1(m1->getNumberOfNodes());
9575   const double *coo2(m2->getCoords()->getConstPointer());
9576   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9577   int offset2(offset1+m2->getNumberOfNodes());
9578   int offset3(offset2+((int)addCoords.size())/2);
9579   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9580   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9581   // Here a BBTree on 2D-cells, not on segments:
9582   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9583   int ncell1(m1->getNumberOfCells());
9584   crI.push_back(0);
9585   for(int i=0;i<ncell1;i++)
9586     {
9587       std::vector<int> candidates2;
9588       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9589       std::map<INTERP_KERNEL::Node *,int> mapp;
9590       std::map<int,INTERP_KERNEL::Node *> mappRev;
9591       INTERP_KERNEL::QuadraticPolygon pol1;
9592       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9593       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9594       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9595       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9596       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9597       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9598           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9599       //
9600       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
9601       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9602       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9603       for(it1.first();!it1.finished();it1.next())
9604         edges1.insert(it1.current()->getPtr());
9605       //
9606       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9607       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9608       int ii=0;
9609       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9610         {
9611           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9612           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9613           // Complete mapping with elements coming from the current cell it2 in mesh2:
9614           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9615           // pol2 is the new QP in the final merged result.
9616           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9617               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9618         }
9619       ii=0;
9620       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9621         {
9622           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9623           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9624           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9625           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9626         }
9627       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9628       // by m2 but that we still want to keep in the final result.
9629       if(!edges1.empty())
9630         {
9631           try
9632           {
9633               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9634           }
9635           catch(INTERP_KERNEL::Exception& e)
9636           {
9637               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();
9638               throw INTERP_KERNEL::Exception(oss.str().c_str());
9639           }
9640         }
9641       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9642         (*it).second->decrRef();
9643     }
9644 }
9645
9646 /**
9647  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9648  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9649  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9650  * The caller is to deal with the resulting DataArrayInt.
9651  *  \throw If the coordinate array is not set.
9652  *  \throw If the nodal connectivity of the cells is not defined.
9653  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9654  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9655  */
9656 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9657 {
9658   checkFullyDefined();
9659   if(getMeshDimension()!=1)
9660     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9661
9662   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9663   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9664   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9665   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9666   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9667   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9668   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9669   const int * dsi(_dsi->getConstPointer());
9670   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9671   m_points=0;
9672   if (dsii->getNumberOfTuples())
9673     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9674
9675   int nc(getNumberOfCells());
9676   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9677   result->alloc(nc,1);
9678
9679   // set of edges not used so far
9680   std::set<int> edgeSet;
9681   for (int i=0; i<nc; edgeSet.insert(i), i++);
9682
9683   int startSeg=0;
9684   int newIdx=0;
9685   // while we have points with only one neighbor segments
9686   do
9687     {
9688       std::list<int> linePiece;
9689       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9690       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9691         {
9692           // Fill the list forward (resp. backward) from the start segment:
9693           int activeSeg = startSeg;
9694           int prevPointId = -20;
9695           int ptId;
9696           while (!edgeSet.empty())
9697             {
9698               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9699                 {
9700                   if (direction==0)
9701                     linePiece.push_back(activeSeg);
9702                   else
9703                     linePiece.push_front(activeSeg);
9704                   edgeSet.erase(activeSeg);
9705                 }
9706
9707               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9708               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9709               if (dsi[ptId] == 1) // hitting the end of the line
9710                 break;
9711               prevPointId = ptId;
9712               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9713               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9714             }
9715         }
9716       // Done, save final piece into DA:
9717       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9718       newIdx += linePiece.size();
9719
9720       // identify next valid start segment (one which is not consumed)
9721       if(!edgeSet.empty())
9722         startSeg = *(edgeSet.begin());
9723     }
9724   while (!edgeSet.empty());
9725   return result.retn();
9726 }
9727
9728 /// @cond INTERNAL
9729
9730 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9731 {
9732   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9733   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9734   if(it==m.end())
9735     throw INTERP_KERNEL::Exception("Internal error in remapping !");
9736   int v((*it).second);
9737   if(v==forbVal0 || v==forbVal1)
9738     return ;
9739   if(std::find(isect.begin(),isect.end(),v)==isect.end())
9740     isect.push_back(v);
9741 }
9742
9743 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9744 {
9745   int sz(c.size());
9746   if(sz<=1)
9747     return false;
9748   bool presenceOfOn(false);
9749   for(int i=0;i<sz;i++)
9750     {
9751       INTERP_KERNEL::ElementaryEdge *e(c[i]);
9752       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9753         continue ;
9754       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9755       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9756     }
9757   return presenceOfOn;
9758 }
9759
9760 /// @endcond
9761
9762 /**
9763  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
9764  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
9765  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
9766  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
9767  *
9768  * \return int - the number of new nodes created (in most of cases 0).
9769  * 
9770  * \throw If \a this is not coherent.
9771  * \throw If \a this has not spaceDim equal to 2.
9772  * \throw If \a this has not meshDim equal to 2.
9773  * \throw If some subcells needed to be split are orphan.
9774  * \sa MEDCouplingUMesh::conformize2D
9775  */
9776 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9777 {
9778   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9779     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9780   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9781   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9782     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9783   if(midOpt==0 && midOptI==0)
9784     {
9785       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
9786       return 0;
9787     }
9788   else if(midOpt!=0 && midOptI!=0)
9789     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
9790   else
9791     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
9792 }
9793
9794 /*!
9795  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
9796  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
9797  * 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
9798  * 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).
9799  * 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.
9800  * 
9801  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
9802  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
9803  *
9804  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
9805  * This method expects that all nodes in \a this are not closer than \a eps.
9806  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
9807  * 
9808  * \param [in] eps the relative error to detect merged edges.
9809  * \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
9810  *                           that the user is expected to deal with.
9811  *
9812  * \throw If \a this is not coherent.
9813  * \throw If \a this has not spaceDim equal to 2.
9814  * \throw If \a this has not meshDim equal to 2.
9815  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
9816  */
9817 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
9818 {
9819   static const int SPACEDIM=2;
9820   checkCoherency();
9821   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9822     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9823   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
9824   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
9825   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
9826   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
9827   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
9828   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
9829   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
9830   std::vector<double> addCoo;
9831   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
9832   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9833   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9834   for(int i=0;i<nDescCell;i++)
9835     {
9836       std::vector<int> candidates;
9837       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
9838       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9839         if(*it>i)
9840           {
9841             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9842             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
9843                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
9844             INTERP_KERNEL::MergePoints merge;
9845             INTERP_KERNEL::QuadraticPolygon c1,c2;
9846             e1->intersectWith(e2,merge,c1,c2);
9847             e1->decrRef(); e2->decrRef();
9848             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
9849               overlapEdge[i].push_back(*it);
9850             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
9851               overlapEdge[*it].push_back(i);
9852           }
9853     }
9854   // splitting done. sort intersect point in intersectEdge.
9855   std::vector< std::vector<int> > middle(nDescCell);
9856   int nbOf2DCellsToBeSplit(0);
9857   bool middleNeedsToBeUsed(false);
9858   std::vector<bool> cells2DToTreat(nDescCell,false);
9859   for(int i=0;i<nDescCell;i++)
9860     {
9861       std::vector<int>& isect(intersectEdge[i]);
9862       int sz((int)isect.size());
9863       if(sz>1)
9864         {
9865           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9866           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
9867           e->sortSubNodesAbs(coords,isect);
9868           e->decrRef();
9869         }
9870       if(sz!=0)
9871         {
9872           int idx0(rdi[i]),idx1(rdi[i+1]);
9873           if(idx1-idx0!=1)
9874             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
9875           if(!cells2DToTreat[rd[idx0]])
9876             {
9877               cells2DToTreat[rd[idx0]]=true;
9878               nbOf2DCellsToBeSplit++;
9879             }
9880           // try to reuse at most eventual 'middle' of SEG3
9881           std::vector<int>& mid(middle[i]);
9882           mid.resize(sz+1,-1);
9883           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
9884             {
9885               middleNeedsToBeUsed=true;
9886               const std::vector<int>& candidates(overlapEdge[i]);
9887               std::vector<int> trueCandidates;
9888               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
9889                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
9890                   trueCandidates.push_back(*itc);
9891               int stNode(c[ci[i]+1]),endNode(isect[0]);
9892               for(int j=0;j<sz+1;j++)
9893                 {
9894                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
9895                     {
9896                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
9897                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
9898                         { mid[j]=*itc; break; }
9899                     }
9900                   stNode=endNode;
9901                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
9902                 }
9903             }
9904         }
9905     }
9906   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
9907   if(nbOf2DCellsToBeSplit==0)
9908     return ret.retn();
9909   //
9910   int *retPtr(ret->getPointer());
9911   for(int i=0;i<nCell;i++)
9912     if(cells2DToTreat[i])
9913       *retPtr++=i;
9914   //
9915   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
9916   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
9917   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
9918   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
9919   if(middleNeedsToBeUsed)
9920     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
9921   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
9922   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
9923   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.
9924   setPartOfMySelf(ret->begin(),ret->end(),*modif);
9925   {
9926     bool areNodesMerged; int newNbOfNodes;
9927     if(nbOfNodesCreated!=0)
9928       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
9929   }
9930   return ret.retn();
9931 }
9932
9933 /*!
9934  * 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.
9935  * 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).
9936  * 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
9937  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
9938  * 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
9939  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
9940  *
9941  * 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
9942  * using new instance, idem for coordinates.
9943  *
9944  * 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.
9945  * 
9946  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
9947  *
9948  * \throw If \a this is not coherent.
9949  * \throw If \a this has not spaceDim equal to 2.
9950  * \throw If \a this has not meshDim equal to 2.
9951  * 
9952  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9953  */
9954 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9955 {
9956   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9957   checkCoherency();
9958   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9959     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9960   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9961   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9962   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9963   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9964   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9965   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9966   const double *coords(_coords->begin());
9967   int *newciptr(newci->getPointer());
9968   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9969     {
9970       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9971         ret->pushBackSilent(i);
9972       newciptr[1]=newc->getNumberOfTuples();
9973     }
9974   //
9975   if(ret->empty())
9976     return ret.retn();
9977   if(!appendedCoords->empty())
9978     {
9979       appendedCoords->rearrange(2);
9980       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9981       //non const part
9982       setCoords(newCoords);
9983     }
9984   //non const part
9985   setConnectivity(newc,newci,true);
9986   return ret.retn();
9987 }
9988
9989 /*!
9990  * \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.
9991  *                               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.
9992  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
9993  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
9994  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
9995  * \param [out] addCoo - nodes to be append at the end
9996  * \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.
9997  */
9998 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
9999                                          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)
10000 {
10001   static const int SPACEDIM=2;
10002   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10003   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10004   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10005   // Build BB tree of all edges in the tool mesh (second mesh)
10006   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10007   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10008   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10009   intersectEdge1.resize(nDescCell1);
10010   colinear2.resize(nDescCell2);
10011   subDiv2.resize(nDescCell2);
10012   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10013
10014   std::vector<int> candidates1(1);
10015   int offset1(m1Desc->getNumberOfNodes());
10016   int offset2(offset1+m2Desc->getNumberOfNodes());
10017   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10018     {
10019       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10020       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10021       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10022         {
10023           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10024           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10025           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10026           candidates1[0]=i;
10027           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10028           // 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
10029           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10030           std::set<INTERP_KERNEL::Node *> nodes;
10031           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10032           std::size_t szz(nodes.size());
10033           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10034           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10035           for(std::size_t iii=0;iii<szz;iii++,itt++)
10036             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10037           // end of protection
10038           // Performs egde cutting:
10039           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10040           delete pol2;
10041           delete pol1;
10042         }
10043       else
10044         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
10045     }
10046 }
10047
10048 /*!
10049  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10050  * It builds the descending connectivity of the two meshes, and then using a binary tree
10051  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10052  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10053  */
10054 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10055                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10056                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10057                                                    std::vector<double>& addCoo,
10058                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10059 {
10060   // Build desc connectivity
10061   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10062   desc2=DataArrayInt::New();
10063   descIndx2=DataArrayInt::New();
10064   revDesc2=DataArrayInt::New();
10065   revDescIndx2=DataArrayInt::New();
10066   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10067   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10068   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10069   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10070   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10071   std::map<int,int> notUsedMap;
10072   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10073   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10074   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10075 }
10076
10077 /*!
10078  * This method performs the 2nd step of Partition of 2D mesh.
10079  * This method has 4 inputs :
10080  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10081  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10082  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10083  * 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'
10084  * Nodes end up lying consecutively on a cutted edge.
10085  * \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.
10086  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10087  * \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.
10088  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10089  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10090  */
10091 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10092                                            const std::vector<double>& addCoo,
10093                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10094 {
10095   int offset1=m1->getNumberOfNodes();
10096   int ncell=m2->getNumberOfCells();
10097   const int *c=m2->getNodalConnectivity()->getConstPointer();
10098   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10099   const double *coo=m2->getCoords()->getConstPointer();
10100   const double *cooBis=m1->getCoords()->getConstPointer();
10101   int offset2=offset1+m2->getNumberOfNodes();
10102   intersectEdge.resize(ncell);
10103   for(int i=0;i<ncell;i++,cI++)
10104     {
10105       const std::vector<int>& divs=subDiv[i];
10106       int nnode=cI[1]-cI[0]-1;
10107       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10108       std::map<INTERP_KERNEL::Node *, int> mapp22;
10109       for(int j=0;j<nnode;j++)
10110         {
10111           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10112           int nnid=c[(*cI)+j+1];
10113           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10114           mapp22[nn]=nnid+offset1;
10115         }
10116       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10117       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10118         ((*it).second.first)->decrRef();
10119       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10120       std::map<INTERP_KERNEL::Node *,int> mapp3;
10121       for(std::size_t j=0;j<divs.size();j++)
10122         {
10123           int id=divs[j];
10124           INTERP_KERNEL::Node *tmp=0;
10125           if(id<offset1)
10126             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10127           else if(id<offset2)
10128             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10129           else
10130             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10131           addNodes[j]=tmp;
10132           mapp3[tmp]=id;
10133         }
10134       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10135       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10136         (*it)->decrRef();
10137       e->decrRef();
10138     }
10139 }
10140
10141 /*!
10142  * 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).
10143  * 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
10144  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10145  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10146  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10147  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10148  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10149  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10150  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10151  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10152  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10153  * \param [out] cut3DSuf input/output param.
10154  */
10155 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10156                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10157                                                    const int *desc, const int *descIndx, 
10158                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10159 {
10160   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10161   int nbOf3DSurfCell=(int)cut3DSurf.size();
10162   for(int i=0;i<nbOf3DSurfCell;i++)
10163     {
10164       std::vector<int> res;
10165       int offset=descIndx[i];
10166       int nbOfSeg=descIndx[i+1]-offset;
10167       for(int j=0;j<nbOfSeg;j++)
10168         {
10169           int edgeId=desc[offset+j];
10170           int status=cut3DCurve[edgeId];
10171           if(status!=-2)
10172             {
10173               if(status>-1)
10174                 res.push_back(status);
10175               else
10176                 {
10177                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10178                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10179                 }
10180             }
10181         }
10182       switch(res.size())
10183       {
10184         case 2:
10185           {
10186             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10187             break;
10188           }
10189         case 1:
10190         case 0:
10191           {
10192             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10193             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10194             if(res.size()==2)
10195               {
10196                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10197               }
10198             else
10199               {
10200                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10201               }
10202             break;
10203           }
10204         default:
10205           {// case when plane is on a multi colinear edge of a polyhedron
10206             if((int)res.size()==2*nbOfSeg)
10207               {
10208                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10209               }
10210             else
10211               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10212           }
10213       }
10214     }
10215 }
10216
10217 /*!
10218  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10219  * 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).
10220  * 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
10221  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10222  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10223  * \param desc is the descending connectivity 3D->3DSurf
10224  * \param descIndx is the descending connectivity index 3D->3DSurf
10225  */
10226 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10227                                                   const int *desc, const int *descIndx,
10228                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10229 {
10230   checkFullyDefined();
10231   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10232     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10233   const int *nodal3D=_nodal_connec->getConstPointer();
10234   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10235   int nbOfCells=getNumberOfCells();
10236   for(int i=0;i<nbOfCells;i++)
10237     {
10238       std::map<int, std::set<int> > m;
10239       int offset=descIndx[i];
10240       int nbOfFaces=descIndx[i+1]-offset;
10241       int start=-1;
10242       int end=-1;
10243       for(int j=0;j<nbOfFaces;j++)
10244         {
10245           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10246           if(p.first!=-1 && p.second!=-1)
10247             {
10248               if(p.first!=-2)
10249                 {
10250                   start=p.first; end=p.second;
10251                   m[p.first].insert(p.second);
10252                   m[p.second].insert(p.first);
10253                 }
10254               else
10255                 {
10256                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10257                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10258                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10259                   INTERP_KERNEL::NormalizedCellType cmsId;
10260                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10261                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10262                   for(unsigned k=0;k<nbOfNodesSon;k++)
10263                     {
10264                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10265                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10266                     }
10267                 }
10268             }
10269         }
10270       if(m.empty())
10271         continue;
10272       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10273       int prev=end;
10274       while(end!=start)
10275         {
10276           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10277           const std::set<int>& s=(*it).second;
10278           std::set<int> s2; s2.insert(prev);
10279           std::set<int> s3;
10280           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10281           if(s3.size()==1)
10282             {
10283               int val=*s3.begin();
10284               conn.push_back(start);
10285               prev=start;
10286               start=val;
10287             }
10288           else
10289             start=end;
10290         }
10291       conn.push_back(end);
10292       if(conn.size()>3)
10293         {
10294           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10295           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10296           cellIds->pushBackSilent(i);
10297         }
10298     }
10299 }
10300
10301 /*!
10302  * 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
10303  * 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
10304  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10305  * 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
10306  * 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.
10307  * 
10308  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10309  */
10310 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10311 {
10312   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10313   if(sz>=4)
10314     {
10315       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10316       if(cm.getDimension()==2)
10317         {
10318           const int *node=nodalConnBg+1;
10319           int startNode=*node++;
10320           double refX=coords[2*startNode];
10321           for(;node!=nodalConnEnd;node++)
10322             {
10323               if(coords[2*(*node)]<refX)
10324                 {
10325                   startNode=*node;
10326                   refX=coords[2*startNode];
10327                 }
10328             }
10329           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10330           refX=1e300;
10331           double tmp1;
10332           double tmp2[2];
10333           double angle0=-M_PI/2;
10334           //
10335           int nextNode=-1;
10336           int prevNode=-1;
10337           double resRef;
10338           double angleNext=0.;
10339           while(nextNode!=startNode)
10340             {
10341               nextNode=-1;
10342               resRef=1e300;
10343               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10344                 {
10345                   if(*node!=tmpOut.back() && *node!=prevNode)
10346                     {
10347                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10348                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10349                       double res;
10350                       if(angleM<=angle0)
10351                         res=angle0-angleM;
10352                       else
10353                         res=angle0-angleM+2.*M_PI;
10354                       if(res<resRef)
10355                         {
10356                           nextNode=*node;
10357                           resRef=res;
10358                           angleNext=angleM;
10359                         }
10360                     }
10361                 }
10362               if(nextNode!=startNode)
10363                 {
10364                   angle0=angleNext-M_PI;
10365                   if(angle0<-M_PI)
10366                     angle0+=2*M_PI;
10367                   prevNode=tmpOut.back();
10368                   tmpOut.push_back(nextNode);
10369                 }
10370             }
10371           std::vector<int> tmp3(2*(sz-1));
10372           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10373           std::copy(nodalConnBg+1,nodalConnEnd,it);
10374           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10375             {
10376               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10377               return false;
10378             }
10379           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10380             {
10381               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10382               return false;
10383             }
10384           else
10385             {
10386               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10387               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10388               return true;
10389             }
10390         }
10391       else
10392         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10393     }
10394   else
10395     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10396 }
10397
10398 /*!
10399  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10400  * 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.
10401  * 
10402  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10403  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10404  * \param [in,out] arr array in which the remove operation will be done.
10405  * \param [in,out] arrIndx array in the remove operation will modify
10406  * \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])
10407  * \return true if \b arr and \b arrIndx have been modified, false if not.
10408  */
10409 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10410 {
10411   if(!arrIndx || !arr)
10412     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10413   if(offsetForRemoval<0)
10414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10415   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10416   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10417   int *arrIPtr=arrIndx->getPointer();
10418   *arrIPtr++=0;
10419   int previousArrI=0;
10420   const int *arrPtr=arr->getConstPointer();
10421   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10422   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10423     {
10424       if(*arrIPtr-previousArrI>offsetForRemoval)
10425         {
10426           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10427             {
10428               if(s.find(*work)==s.end())
10429                 arrOut.push_back(*work);
10430             }
10431         }
10432       previousArrI=*arrIPtr;
10433       *arrIPtr=(int)arrOut.size();
10434     }
10435   if(arr->getNumberOfTuples()==(int)arrOut.size())
10436     return false;
10437   arr->alloc((int)arrOut.size(),1);
10438   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10439   return true;
10440 }
10441
10442 /*!
10443  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10444  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10445  * The selection of extraction is done standardly in new2old format.
10446  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10447  *
10448  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10449  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10450  * \param [in] arrIn arr origin array from which the extraction will be done.
10451  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10452  * \param [out] arrOut the resulting array
10453  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10454  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10455  */
10456 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10457                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10458 {
10459   if(!arrIn || !arrIndxIn)
10460     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10461   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10462   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10463     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10464   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10465   const int *arrInPtr=arrIn->getConstPointer();
10466   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10467   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10468   if(nbOfGrps<0)
10469     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10470   int maxSizeOfArr=arrIn->getNumberOfTuples();
10471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10472   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10473   arrIo->alloc((int)(sz+1),1);
10474   const int *idsIt=idsOfSelectBg;
10475   int *work=arrIo->getPointer();
10476   *work++=0;
10477   int lgth=0;
10478   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10479     {
10480       if(*idsIt>=0 && *idsIt<nbOfGrps)
10481         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10482       else
10483         {
10484           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10485           throw INTERP_KERNEL::Exception(oss.str().c_str());
10486         }
10487       if(lgth>=work[-1])
10488         *work=lgth;
10489       else
10490         {
10491           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10492           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10493           throw INTERP_KERNEL::Exception(oss.str().c_str());
10494         }
10495     }
10496   arro->alloc(lgth,1);
10497   work=arro->getPointer();
10498   idsIt=idsOfSelectBg;
10499   for(std::size_t i=0;i<sz;i++,idsIt++)
10500     {
10501       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10502         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10503       else
10504         {
10505           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10506           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10507           throw INTERP_KERNEL::Exception(oss.str().c_str());
10508         }
10509     }
10510   arrOut=arro.retn();
10511   arrIndexOut=arrIo.retn();
10512 }
10513
10514 /*!
10515  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10516  * 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 ).
10517  * The selection of extraction is done standardly in new2old format.
10518  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10519  *
10520  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10521  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10522  * \param [in] arrIn arr origin array from which the extraction will be done.
10523  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10524  * \param [out] arrOut the resulting array
10525  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10526  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10527  */
10528 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10529                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10530 {
10531   if(!arrIn || !arrIndxIn)
10532     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10533   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10534   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10535     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10536   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10537   const int *arrInPtr=arrIn->getConstPointer();
10538   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10539   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10540   if(nbOfGrps<0)
10541     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10542   int maxSizeOfArr=arrIn->getNumberOfTuples();
10543   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10544   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10545   arrIo->alloc((int)(sz+1),1);
10546   int idsIt=idsOfSelectStart;
10547   int *work=arrIo->getPointer();
10548   *work++=0;
10549   int lgth=0;
10550   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10551     {
10552       if(idsIt>=0 && idsIt<nbOfGrps)
10553         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10554       else
10555         {
10556           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10557           throw INTERP_KERNEL::Exception(oss.str().c_str());
10558         }
10559       if(lgth>=work[-1])
10560         *work=lgth;
10561       else
10562         {
10563           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10564           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10565           throw INTERP_KERNEL::Exception(oss.str().c_str());
10566         }
10567     }
10568   arro->alloc(lgth,1);
10569   work=arro->getPointer();
10570   idsIt=idsOfSelectStart;
10571   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10572     {
10573       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10574         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10575       else
10576         {
10577           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10578           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10579           throw INTERP_KERNEL::Exception(oss.str().c_str());
10580         }
10581     }
10582   arrOut=arro.retn();
10583   arrIndexOut=arrIo.retn();
10584 }
10585
10586 /*!
10587  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10588  * 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
10589  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10590  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10591  *
10592  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10593  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10594  * \param [in] arrIn arr origin array from which the extraction will be done.
10595  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10596  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10597  * \param [in] srcArrIndex index array of \b srcArr
10598  * \param [out] arrOut the resulting array
10599  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10600  * 
10601  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10602  */
10603 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10604                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10605                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10606 {
10607   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10608     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10609   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10610   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10611   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10612   std::vector<bool> v(nbOfTuples,true);
10613   int offset=0;
10614   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10615   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10616   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10617     {
10618       if(*it>=0 && *it<nbOfTuples)
10619         {
10620           v[*it]=false;
10621           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10622         }
10623       else
10624         {
10625           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10626           throw INTERP_KERNEL::Exception(oss.str().c_str());
10627         }
10628     }
10629   srcArrIndexPtr=srcArrIndex->getConstPointer();
10630   arrIo->alloc(nbOfTuples+1,1);
10631   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10632   const int *arrInPtr=arrIn->getConstPointer();
10633   const int *srcArrPtr=srcArr->getConstPointer();
10634   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10635   int *arroPtr=arro->getPointer();
10636   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10637     {
10638       if(v[ii])
10639         {
10640           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10641           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10642         }
10643       else
10644         {
10645           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10646           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10647           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10648         }
10649     }
10650   arrOut=arro.retn();
10651   arrIndexOut=arrIo.retn();
10652 }
10653
10654 /*!
10655  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10656  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10657  *
10658  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10659  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10660  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10661  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10662  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10663  * \param [in] srcArrIndex index array of \b srcArr
10664  * 
10665  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10666  */
10667 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10668                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10669 {
10670   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10671     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10672   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10673   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10674   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10675   int *arrInOutPtr=arrInOut->getPointer();
10676   const int *srcArrPtr=srcArr->getConstPointer();
10677   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10678     {
10679       if(*it>=0 && *it<nbOfTuples)
10680         {
10681           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10682             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10683           else
10684             {
10685               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] !";
10686               throw INTERP_KERNEL::Exception(oss.str().c_str());
10687             }
10688         }
10689       else
10690         {
10691           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10692           throw INTERP_KERNEL::Exception(oss.str().c_str());
10693         }
10694     }
10695 }
10696
10697 /*!
10698  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10699  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10700  * 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]].
10701  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10702  * A negative value in \b arrIn means that it is ignored.
10703  * 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.
10704  * 
10705  * \param [in] arrIn arr origin array from which the extraction will be done.
10706  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10707  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10708  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10709  */
10710 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10711 {
10712   int seed=0,nbOfDepthPeelingPerformed=0;
10713   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10714 }
10715
10716 /*!
10717  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10718  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10719  * 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]].
10720  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10721  * A negative value in \b arrIn means that it is ignored.
10722  * 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.
10723  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10724  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10725  * \param [in] arrIn arr origin array from which the extraction will be done.
10726  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10727  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10728  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10729  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10730  * \sa MEDCouplingUMesh::partitionBySpreadZone
10731  */
10732 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10733 {
10734   nbOfDepthPeelingPerformed=0;
10735   if(!arrIndxIn)
10736     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10737   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10738   if(nbOfTuples<=0)
10739     {
10740       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10741       return ret;
10742     }
10743   //
10744   std::vector<bool> fetched(nbOfTuples,false);
10745   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10746 }
10747
10748 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10749 {
10750   nbOfDepthPeelingPerformed=0;
10751   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10752     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10753   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10754   std::vector<bool> fetched2(nbOfTuples,false);
10755   int i=0;
10756   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10757     {
10758       if(*seedElt>=0 && *seedElt<nbOfTuples)
10759         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10760       else
10761         { 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()); }
10762     }
10763   const int *arrInPtr=arrIn->getConstPointer();
10764   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10765   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
10766   std::vector<int> idsToFetch1(seedBg,seedEnd);
10767   std::vector<int> idsToFetch2;
10768   std::vector<int> *idsToFetch=&idsToFetch1;
10769   std::vector<int> *idsToFetchOther=&idsToFetch2;
10770   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
10771     {
10772       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
10773         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
10774           if(!fetched[*it2])
10775             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10776       std::swap(idsToFetch,idsToFetchOther);
10777       idsToFetchOther->clear();
10778       nbOfDepthPeelingPerformed++;
10779     }
10780   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10781   i=0;
10782   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10783   int *retPtr=ret->getPointer();
10784   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
10785     if(*it)
10786       *retPtr++=i;
10787   return ret.retn();
10788 }
10789
10790 /*!
10791  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10792  * 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
10793  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10794  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10795  *
10796  * \param [in] start begin of set of ids of the input extraction (included)
10797  * \param [in] end end of set of ids of the input extraction (excluded)
10798  * \param [in] step step of the set of ids in range mode.
10799  * \param [in] arrIn arr origin array from which the extraction will be done.
10800  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10801  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10802  * \param [in] srcArrIndex index array of \b srcArr
10803  * \param [out] arrOut the resulting array
10804  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10805  * 
10806  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
10807  */
10808 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10809                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10810                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10811 {
10812   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10813     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
10814   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10815   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10816   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10817   int offset=0;
10818   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10819   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10820   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
10821   int it=start;
10822   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10823     {
10824       if(it>=0 && it<nbOfTuples)
10825         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
10826       else
10827         {
10828           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10829           throw INTERP_KERNEL::Exception(oss.str().c_str());
10830         }
10831     }
10832   srcArrIndexPtr=srcArrIndex->getConstPointer();
10833   arrIo->alloc(nbOfTuples+1,1);
10834   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10835   const int *arrInPtr=arrIn->getConstPointer();
10836   const int *srcArrPtr=srcArr->getConstPointer();
10837   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10838   int *arroPtr=arro->getPointer();
10839   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10840     {
10841       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
10842       if(pos<0)
10843         {
10844           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10845           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10846         }
10847       else
10848         {
10849           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10850           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10851         }
10852     }
10853   arrOut=arro.retn();
10854   arrIndexOut=arrIo.retn();
10855 }
10856
10857 /*!
10858  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10859  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10860  *
10861  * \param [in] start begin of set of ids of the input extraction (included)
10862  * \param [in] end end of set of ids of the input extraction (excluded)
10863  * \param [in] step step of the set of ids in range mode.
10864  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10865  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10866  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10867  * \param [in] srcArrIndex index array of \b srcArr
10868  * 
10869  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10870  */
10871 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10872                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10873 {
10874   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10875     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
10876   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10877   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10878   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10879   int *arrInOutPtr=arrInOut->getPointer();
10880   const int *srcArrPtr=srcArr->getConstPointer();
10881   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
10882   int it=start;
10883   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10884     {
10885       if(it>=0 && it<nbOfTuples)
10886         {
10887           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
10888             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
10889           else
10890             {
10891               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
10892               throw INTERP_KERNEL::Exception(oss.str().c_str());
10893             }
10894         }
10895       else
10896         {
10897           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10898           throw INTERP_KERNEL::Exception(oss.str().c_str());
10899         }
10900     }
10901 }
10902
10903 /*!
10904  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
10905  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
10906  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
10907  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
10908  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
10909  * 
10910  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
10911  */
10912 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
10913 {
10914   checkFullyDefined();
10915   int mdim=getMeshDimension();
10916   int spaceDim=getSpaceDimension();
10917   if(mdim!=spaceDim)
10918     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
10919   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
10920   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
10921   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
10922   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
10923   ret->setCoords(getCoords());
10924   ret->allocateCells((int)partition.size());
10925   //
10926   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
10927     {
10928       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
10929       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
10930       switch(mdim)
10931       {
10932         case 2:
10933           cell=tmp->buildUnionOf2DMesh();
10934           break;
10935         case 3:
10936           cell=tmp->buildUnionOf3DMesh();
10937           break;
10938         default:
10939           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
10940       }
10941
10942       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
10943     }
10944   //
10945   ret->finishInsertingCells();
10946   return ret.retn();
10947 }
10948
10949 /*!
10950  * This method partitions \b this into contiguous zone.
10951  * This method only needs a well defined connectivity. Coordinates are not considered here.
10952  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
10953  */
10954 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
10955 {
10956   int nbOfCellsCur=getNumberOfCells();
10957   std::vector<DataArrayInt *> ret;
10958   if(nbOfCellsCur<=0)
10959     return ret;
10960   DataArrayInt *neigh=0,*neighI=0;
10961   computeNeighborsOfCells(neigh,neighI);
10962   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10963   std::vector<bool> fetchedCells(nbOfCellsCur,false);
10964   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10965   int seed=0;
10966   while(seed<nbOfCellsCur)
10967     {
10968       int nbOfPeelPerformed=0;
10969       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10970       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10971     }
10972   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10973     ret.push_back((*it).retn());
10974   return ret;
10975 }
10976
10977 /*!
10978  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10979  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10980  *
10981  * \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.
10982  * \return a newly allocated DataArrayInt to be managed by the caller.
10983  * \throw In case of \a code has not the right format (typically of size 3*n)
10984  */
10985 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10986 {
10987   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10988   std::size_t nb=code.size()/3;
10989   if(code.size()%3!=0)
10990     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10991   ret->alloc((int)nb,2);
10992   int *retPtr=ret->getPointer();
10993   for(std::size_t i=0;i<nb;i++,retPtr+=2)
10994     {
10995       retPtr[0]=code[3*i+2];
10996       retPtr[1]=code[3*i+2]+code[3*i+1];
10997     }
10998   return ret.retn();
10999 }
11000
11001 /*!
11002  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11003  * All cells in \a this are expected to be linear 3D cells.
11004  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11005  * It leads to an increase to number of cells.
11006  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11007  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11008  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11009  *
11010  * \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.
11011  *                      For all other cells, the splitting policy will be ignored.
11012  * \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. 
11013  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11014  *          an id of old cell producing it. The caller is to delete this array using
11015  *         decrRef() as it is no more needed.
11016  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11017  *
11018  * \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
11019  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11020  * 
11021  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11022  * \throw If \a this is not fully constituted with linear 3D cells.
11023  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11024  */
11025 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11026 {
11027   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11028   checkConnectivityFullyDefined();
11029   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11030     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11031   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11032   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11033   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11034   int *retPt(ret->getPointer());
11035   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11036   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11037   const int *oldc(_nodal_connec->begin());
11038   const int *oldci(_nodal_connec_index->begin());
11039   const double *coords(_coords->begin());
11040   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11041     {
11042       std::vector<int> a; std::vector<double> b;
11043       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11044       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11045       const int *aa(&a[0]);
11046       if(!b.empty())
11047         {
11048           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11049             if(*it<0)
11050               *it=(-(*(it))-1+nbNodes);
11051           addPts->insertAtTheEnd(b.begin(),b.end());
11052           nbNodes+=(int)b.size()/3;
11053         }
11054       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11055         newConn->insertAtTheEnd(aa,aa+4);
11056     }
11057   if(!addPts->empty())
11058     {
11059       addPts->rearrange(3);
11060       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11061       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11062       ret0->setCoords(addPts);
11063     }
11064   else
11065     {
11066       nbOfAdditionalPoints=0;
11067       ret0->setCoords(getCoords());
11068     }
11069   ret0->setNodalConnectivity(newConn);
11070   //
11071   ret->computeOffsets2();
11072   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11073   return ret0.retn();
11074 }
11075
11076 /*!
11077  * 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). 
11078  *
11079  * \sa MEDCouplingUMesh::split2DCells
11080  */
11081 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11082 {
11083   checkConnectivityFullyDefined();
11084   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11085   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11086   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11087   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11088   int prevPosOfCi(ciPtr[0]);
11089   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11090     {
11091       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11092       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11093       for(int j=0;j<sz;j++)
11094         {
11095           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11096           for(int k=0;k<sz2;k++)
11097             *cPtr++=subPtr[offset2+k];
11098           if(j!=sz-1)
11099             *cPtr++=oldConn[prevPosOfCi+j+2];
11100           deltaSz+=sz2;
11101         }
11102       prevPosOfCi=ciPtr[1];
11103       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11104     }
11105   if(c->end()!=cPtr)
11106     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11107   _nodal_connec->decrRef();
11108   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11109 }
11110
11111 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11112 {
11113   if(id!=-1)
11114     return id;
11115   else
11116     {
11117       int ret(nodesCnter++);
11118       double newPt[2];
11119       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11120       addCoo.insertAtTheEnd(newPt,newPt+2);
11121       return ret;
11122     }
11123 }
11124
11125 /// @cond INTERNAL
11126
11127 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)
11128 {
11129   int tmp[3];
11130   int trueStart(start>=0?start:nbOfEdges+start);
11131   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11132   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11133   if(linOrArc)
11134     {
11135       if(stp-start>1)
11136         {
11137           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11138           InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11139           middles.push_back(tmp3+offset);
11140         }
11141       else
11142         middles.push_back(connBg[trueStart+nbOfEdges]);
11143     }
11144 }
11145
11146 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)
11147 {
11148   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11149   newConnOfCell->pushBackSilent(tmpEnd);
11150   if(linOrArc)
11151     {
11152       if(stp-start>1)
11153         {
11154           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11155           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11156           middles.push_back(tmp3+offset);
11157         }
11158       else
11159         middles.push_back(connBg[start+nbOfEdges]);
11160     }
11161 }
11162
11163 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)
11164 {
11165   if(linOrArc)
11166     {
11167       if(stp-start>1)
11168         {
11169           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11170           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11171           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11172           middles.push_back(tmp3+offset);
11173         }
11174       else
11175         middles.push_back(connBg[start+nbOfEdges]);
11176     }
11177 }
11178
11179 /// @cond INTERNAL
11180
11181 /*!
11182  * 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 ) .
11183  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11184  */
11185 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11186 {
11187   std::size_t sz(std::distance(connBg,connEnd));
11188   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11189     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11190   sz--;
11191   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11192   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11193   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
11194   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11195   INTERP_KERNEL::NormalizedCellType typeOfSon;
11196   std::vector<int> middles;
11197   bool ret(false);
11198   for(;nbOfHit<nbs;nbOfTurn++)
11199     {
11200       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11201       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11202       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11203       posEndElt++;
11204       nbOfHit++;
11205       unsigned endI(nbs-nbOfHit);
11206       for(unsigned i=0;i<endI;i++)
11207         {
11208           cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
11209           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11210           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11211           bool isColinear(eint->areColinears());
11212           if(isColinear)
11213             {
11214               nbOfHit++;
11215               posEndElt++;
11216               ret=true;
11217             }
11218           delete eint;
11219           eCand->decrRef();
11220           if(!isColinear)
11221             {
11222               if(nbOfTurn==0)
11223                 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
11224                   unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
11225                   for(unsigned ii=0;ii<endII;ii++)
11226                     {
11227                       cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
11228                       eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
11229                       eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
11230                       isColinear=eint->areColinears();
11231                       if(isColinear)
11232                         {
11233                           nbOfHit++;
11234                           posBaseElt--;
11235                           ret=true;
11236                         }
11237                       delete eint;
11238                       eCand->decrRef();
11239                       if(!isColinear)
11240                         break;
11241                     }
11242                 }
11243               break;
11244             }
11245         }
11246       //push [posBaseElt,posEndElt) in newConnOfCell using e
11247       if(nbOfTurn==0)
11248         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11249       else if(nbOfHit!=nbs)
11250         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11251       else
11252         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11253       posBaseElt=posEndElt;
11254       e->decrRef();
11255     }
11256   if(!middles.empty())
11257     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11258   return ret;
11259 }
11260
11261 /*!
11262  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11263  *
11264  * \return  int - the number of new nodes created.
11265  * \sa MEDCouplingUMesh::split2DCells
11266  */
11267 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11268 {
11269   checkCoherency();
11270   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11271   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11272   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11273   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11274   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11275   const double *oldCoordsPtr(getCoords()->begin());
11276   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11277   int prevPosOfCi(ciPtr[0]);
11278   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11279     {
11280       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11281       for(int j=0;j<sz;j++)
11282         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11283       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11284       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11285         {
11286           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11287           if(sz2==0)
11288             {
11289               if(j<sz-1)
11290                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11291               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11292               continue;
11293             }
11294           std::vector<INTERP_KERNEL::Node *> ns(3);
11295           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11296           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11297           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11298           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11299           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11300             {
11301               cPtr[1]=subPtr[offset2+k];
11302               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11303             }
11304           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11305           if(j!=sz-1)
11306             { cPtr[1]=tmpEnd; }
11307           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11308         }
11309       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11310       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11311     }
11312   if(c->end()!=cPtr)
11313     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11314   _nodal_connec->decrRef();
11315   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11316   addCoo->rearrange(2);
11317   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11318   setCoords(coo);
11319   return addCoo->getNumberOfTuples();
11320 }
11321
11322 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11323     _own_cell(true),_cell_id(-1),_nb_cell(0)
11324 {
11325   if(mesh)
11326     {
11327       mesh->incrRef();
11328       _nb_cell=mesh->getNumberOfCells();
11329     }
11330 }
11331
11332 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11333 {
11334   if(_mesh)
11335     _mesh->decrRef();
11336   if(_own_cell)
11337     delete _cell;
11338 }
11339
11340 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11341     _own_cell(false),_cell_id(bg-1),
11342     _nb_cell(end)
11343 {
11344   if(mesh)
11345     mesh->incrRef();
11346 }
11347
11348 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11349 {
11350   _cell_id++;
11351   if(_cell_id<_nb_cell)
11352     {
11353       _cell->next();
11354       return _cell;
11355     }
11356   else
11357     return 0;
11358 }
11359
11360 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11361 {
11362   if(_mesh)
11363     _mesh->incrRef();
11364 }
11365
11366 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11367 {
11368   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11369 }
11370
11371 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11372 {
11373   if(_mesh)
11374     _mesh->decrRef();
11375 }
11376
11377 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11378     _itc(itc),
11379     _bg(bg),_end(end)
11380 {
11381   if(_mesh)
11382     _mesh->incrRef();
11383 }
11384
11385 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11386 {
11387   if(_mesh)
11388     _mesh->decrRef();
11389 }
11390
11391 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11392 {
11393   return _type;
11394 }
11395
11396 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11397 {
11398   return _end-_bg;
11399 }
11400
11401 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11402 {
11403   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11404 }
11405
11406 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11407 {
11408   if(mesh)
11409     {
11410       mesh->incrRef();
11411       _nb_cell=mesh->getNumberOfCells();
11412     }
11413 }
11414
11415 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11416 {
11417   if(_mesh)
11418     _mesh->decrRef();
11419   delete _cell;
11420 }
11421
11422 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11423 {
11424   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11425   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11426   if(_cell_id<_nb_cell)
11427     {
11428       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11429       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11430       int startId=_cell_id;
11431       _cell_id+=nbOfElems;
11432       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11433     }
11434   else
11435     return 0;
11436 }
11437
11438 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11439 {
11440   if(mesh)
11441     {
11442       _conn=mesh->getNodalConnectivity()->getPointer();
11443       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11444     }
11445 }
11446
11447 void MEDCouplingUMeshCell::next()
11448 {
11449   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11450     {
11451       _conn+=_conn_lgth;
11452       _conn_indx++;
11453     }
11454   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11455 }
11456
11457 std::string MEDCouplingUMeshCell::repr() const
11458 {
11459   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11460     {
11461       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11462       oss << " : ";
11463       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11464       return oss.str();
11465     }
11466   else
11467     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11468 }
11469
11470 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11471 {
11472   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11473     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11474   else
11475     return INTERP_KERNEL::NORM_ERROR;
11476 }
11477
11478 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11479 {
11480   lgth=_conn_lgth;
11481   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11482     return _conn;
11483   else
11484     return 0;
11485 }