Salome HOME
MEDCouplingUMesh.buildExtrudedMesh feature changed. No more zipCoords performed.
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "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       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3900       if(normm2/normm>1e-6)
3901         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3902       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3903       mw->setCoords(coo);
3904       mw->getBoundingBox(bbox);
3905       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3906       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3907     }
3908   else
3909     {
3910       getBoundingBox(bbox);
3911       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3912       cellIds=getCellsInBoundingBox(bbox,eps);
3913     }
3914   return cellIds.retn();
3915 }
3916
3917 /*!
3918  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3919  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3920  * No consideration of coordinate is done by this method.
3921  * 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)
3922  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3923  */
3924 bool MEDCouplingUMesh::isContiguous1D() const
3925 {
3926   if(getMeshDimension()!=1)
3927     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3928   int nbCells=getNumberOfCells();
3929   if(nbCells<1)
3930     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3931   const int *connI=_nodal_connec_index->getConstPointer();
3932   const int *conn=_nodal_connec->getConstPointer();
3933   int ref=conn[connI[0]+2];
3934   for(int i=1;i<nbCells;i++)
3935     {
3936       if(conn[connI[i]+1]!=ref)
3937         return false;
3938       ref=conn[connI[i]+2];
3939     }
3940   return true;
3941 }
3942
3943 /*!
3944  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3945  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3946  * \param pt reference point of the line
3947  * \param v normalized director vector of the line
3948  * \param eps max precision before throwing an exception
3949  * \param res output of size this->getNumberOfCells
3950  */
3951 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3952 {
3953   if(getMeshDimension()!=1)
3954     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3955   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3956     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3957   if(getSpaceDimension()!=3)
3958     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3959   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3960   const double *fPtr=f->getArray()->getConstPointer();
3961   double tmp[3];
3962   for(int i=0;i<getNumberOfCells();i++)
3963     {
3964       const double *tmp1=fPtr+3*i;
3965       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3966       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3967       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3968       double n1=INTERP_KERNEL::norm<3>(tmp);
3969       n1/=INTERP_KERNEL::norm<3>(tmp1);
3970       if(n1>eps)
3971         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3972     }
3973   const double *coo=getCoords()->getConstPointer();
3974   for(int i=0;i<getNumberOfNodes();i++)
3975     {
3976       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3977       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3978       res[i]=std::accumulate(tmp,tmp+3,0.);
3979     }
3980 }
3981
3982 /*!
3983  * 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. 
3984  * \a this is expected to be a mesh so that its space dimension is equal to its
3985  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3986  * 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).
3987  *
3988  * 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
3989  * 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).
3990  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3991  *
3992  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3993  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3994  *
3995  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3996  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3997  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3998  * \return the positive value of the distance.
3999  * \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
4000  * dimension - 1.
4001  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4002  */
4003 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4004 {
4005   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4006   if(meshDim!=spaceDim-1)
4007     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4008   if(meshDim!=2 && meshDim!=1)
4009     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4010   checkFullyDefined();
4011   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4012     { 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()); }
4013   DataArrayInt *ret1=0;
4014   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4015   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4016   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4017   cellId=*ret1Safe->begin();
4018   return *ret0->begin();
4019 }
4020
4021 /*!
4022  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4023  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4024  * 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
4025  * 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).
4026  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4027  * 
4028  * \a this is expected to be a mesh so that its space dimension is equal to its
4029  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4030  * 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).
4031  *
4032  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4033  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4034  *
4035  * \param [in] pts the list of points in which each tuple represents a point
4036  * \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.
4037  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4038  * \throw if number of components of \a pts is not equal to the space dimension.
4039  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4040  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4041  */
4042 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4043 {
4044   if(!pts)
4045     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4046   pts->checkAllocated();
4047   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4048   if(meshDim!=spaceDim-1)
4049     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4050   if(meshDim!=2 && meshDim!=1)
4051     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4052   if(pts->getNumberOfComponents()!=spaceDim)
4053     {
4054       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4055       throw INTERP_KERNEL::Exception(oss.str().c_str());
4056     }
4057   checkFullyDefined();
4058   int nbCells=getNumberOfCells();
4059   if(nbCells==0)
4060     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4061   int nbOfPts=pts->getNumberOfTuples();
4062   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4063   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4064   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4065   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4066   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4067   const double *bbox(bboxArr->begin());
4068   switch(spaceDim)
4069   {
4070     case 3:
4071       {
4072         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4073         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4074           {
4075             double x=std::numeric_limits<double>::max();
4076             std::vector<int> elems;
4077             myTree.getMinDistanceOfMax(ptsPtr,x);
4078             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4079             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4080           }
4081         break;
4082       }
4083     case 2:
4084       {
4085         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4086         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4087           {
4088             double x=std::numeric_limits<double>::max();
4089             std::vector<int> elems;
4090             myTree.getMinDistanceOfMax(ptsPtr,x);
4091             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4092             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4093           }
4094         break;
4095       }
4096     default:
4097       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4098   }
4099   cellIds=ret1.retn();
4100   return ret0.retn();
4101 }
4102
4103 /*!
4104  * \param [in] pt the start pointer (included) of the coordinates of the point
4105  * \param [in] cellIdsBg the start pointer (included) of cellIds
4106  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4107  * \param [in] nc nodal connectivity
4108  * \param [in] ncI nodal connectivity index
4109  * \param [in,out] ret0 the min distance between \a this and the external input point
4110  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4111  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4112  */
4113 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)
4114 {
4115   cellId=-1;
4116   ret0=std::numeric_limits<double>::max();
4117   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4118     {
4119       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4120       {
4121         case INTERP_KERNEL::NORM_TRI3:
4122           {
4123             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4124             if(tmp<ret0)
4125               { ret0=tmp; cellId=*zeCell; }
4126             break;
4127           }
4128         case INTERP_KERNEL::NORM_QUAD4:
4129         case INTERP_KERNEL::NORM_POLYGON:
4130           {
4131             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4132             if(tmp<ret0)
4133               { ret0=tmp; cellId=*zeCell; }
4134             break;
4135           }
4136         default:
4137           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4138       }
4139     }
4140 }
4141
4142 /*!
4143  * \param [in] pt the start pointer (included) of the coordinates of the point
4144  * \param [in] cellIdsBg the start pointer (included) of cellIds
4145  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4146  * \param [in] nc nodal connectivity
4147  * \param [in] ncI nodal connectivity index
4148  * \param [in,out] ret0 the min distance between \a this and the external input point
4149  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4150  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4151  */
4152 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)
4153 {
4154   cellId=-1;
4155   ret0=std::numeric_limits<double>::max();
4156   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4157     {
4158       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4159       {
4160         case INTERP_KERNEL::NORM_SEG2:
4161           {
4162             std::size_t uselessEntry=0;
4163             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4164             tmp=sqrt(tmp);
4165             if(tmp<ret0)
4166               { ret0=tmp; cellId=*zeCell; }
4167             break;
4168           }
4169         default:
4170           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4171       }
4172     }
4173 }
4174
4175 /*!
4176  * Finds cells in contact with a ball (i.e. a point with precision). 
4177  * 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.
4178  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4179  *
4180  * \warning This method is suitable if the caller intends to evaluate only one
4181  *          point, for more points getCellsContainingPoints() is recommended as it is
4182  *          faster. 
4183  *  \param [in] pos - array of coordinates of the ball central point.
4184  *  \param [in] eps - ball radius.
4185  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4186  *         if there are no such cells.
4187  *  \throw If the coordinates array is not set.
4188  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4189  */
4190 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4191 {
4192   std::vector<int> elts;
4193   getCellsContainingPoint(pos,eps,elts);
4194   if(elts.empty())
4195     return -1;
4196   return elts.front();
4197 }
4198
4199 /*!
4200  * Finds cells in contact with a ball (i.e. a point with precision).
4201  * 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.
4202  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4203  * \warning This method is suitable if the caller intends to evaluate only one
4204  *          point, for more points getCellsContainingPoints() is recommended as it is
4205  *          faster. 
4206  *  \param [in] pos - array of coordinates of the ball central point.
4207  *  \param [in] eps - ball radius.
4208  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4209  *         before inserting ids.
4210  *  \throw If the coordinates array is not set.
4211  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4212  *
4213  *  \if ENABLE_EXAMPLES
4214  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4215  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4216  *  \endif
4217  */
4218 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4219 {
4220   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4221   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4222   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4223 }
4224
4225 /// @cond INTERNAL
4226
4227 namespace ParaMEDMEM
4228 {
4229   template<const int SPACEDIMM>
4230   class DummyClsMCUG
4231   {
4232   public:
4233     static const int MY_SPACEDIM=SPACEDIMM;
4234     static const int MY_MESHDIM=8;
4235     typedef int MyConnType;
4236     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4237     // begin
4238     // useless, but for windows compilation ...
4239     const double* getCoordinatesPtr() const { return 0; }
4240     const int* getConnectivityPtr() const { return 0; }
4241     const int* getConnectivityIndexPtr() const { return 0; }
4242     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4243     // end
4244   };
4245
4246   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4247   {
4248     INTERP_KERNEL::Edge *ret(0);
4249     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]));
4250     m[n0]=bg[0]; m[n1]=bg[1];
4251     switch(typ)
4252     {
4253       case INTERP_KERNEL::NORM_SEG2:
4254         {
4255           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4256           break;
4257         }
4258       case INTERP_KERNEL::NORM_SEG3:
4259         {
4260           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4261           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4262           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4263           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4264           bool colinearity(inters.areColinears());
4265           delete e1; delete e2;
4266           if(colinearity)
4267             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4268           else
4269             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4270           break;
4271         }
4272       default:
4273         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4274     }
4275     return ret;
4276   }
4277
4278   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4279   {
4280     INTERP_KERNEL::Edge *ret=0;
4281     switch(typ)
4282     {
4283       case INTERP_KERNEL::NORM_SEG2:
4284         {
4285           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4286           break;
4287         }
4288       case INTERP_KERNEL::NORM_SEG3:
4289         {
4290           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4291           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4292           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4293           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4294           bool colinearity=inters.areColinears();
4295           delete e1; delete e2;
4296           if(colinearity)
4297             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4298           else
4299             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4300           mapp2[bg[2]].second=false;
4301           break;
4302         }
4303       default:
4304         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4305     }
4306     return ret;
4307   }
4308
4309   /*!
4310    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4311    * the global mesh 'mDesc'.
4312    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4313    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4314    */
4315   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4316                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4317   {
4318     mapp.clear();
4319     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.
4320     const double *coo=mDesc->getCoords()->getConstPointer();
4321     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4322     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4323     std::set<int> s;
4324     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4325       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4326     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4327       {
4328         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4329         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4330       }
4331     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4332     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4333       {
4334         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4335         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4336       }
4337     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4338       {
4339         if((*it2).second.second)
4340           mapp[(*it2).second.first]=(*it2).first;
4341         ((*it2).second.first)->decrRef();
4342       }
4343     return ret;
4344   }
4345
4346   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4347   {
4348     if(nodeId>=offset2)
4349       {
4350         int locId=nodeId-offset2;
4351         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4352       }
4353     if(nodeId>=offset1)
4354       {
4355         int locId=nodeId-offset1;
4356         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4357       }
4358     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4359   }
4360
4361   /**
4362    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4363    */
4364   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4365                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4366                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4367   {
4368     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4369       {
4370         int eltId1=abs(*desc1)-1;
4371         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4372           {
4373             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4374             if(it==mappRev.end())
4375               {
4376                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4377                 mapp[node]=*it1;
4378                 mappRev[*it1]=node;
4379               }
4380           }
4381       }
4382   }
4383 }
4384
4385 /// @endcond
4386
4387 template<int SPACEDIM>
4388 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4389                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4390 {
4391   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4392   int *eltsIndexPtr(eltsIndex->getPointer());
4393   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4394   const double *bbox(bboxArr->begin());
4395   int nbOfCells=getNumberOfCells();
4396   const int *conn=_nodal_connec->getConstPointer();
4397   const int *connI=_nodal_connec_index->getConstPointer();
4398   double bb[2*SPACEDIM];
4399   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4400   for(int i=0;i<nbOfPoints;i++)
4401     {
4402       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4403       for(int j=0;j<SPACEDIM;j++)
4404         {
4405           bb[2*j]=pos[SPACEDIM*i+j];
4406           bb[2*j+1]=pos[SPACEDIM*i+j];
4407         }
4408       std::vector<int> candidates;
4409       myTree.getIntersectingElems(bb,candidates);
4410       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4411         {
4412           int sz(connI[(*iter)+1]-connI[*iter]-1);
4413           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4414           bool status(false);
4415           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4416             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4417           else
4418             {
4419               if(SPACEDIM!=2)
4420                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4421               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4422               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4423               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4424               INTERP_KERNEL::QuadraticPolygon *pol(0);
4425               for(int j=0;j<sz;j++)
4426                 {
4427                   int nodeId(conn[connI[*iter]+1+j]);
4428                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4429                 }
4430               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4431                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4432               else
4433                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4434               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4435               double a(0.),b(0.),c(0.);
4436               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4437               status=pol->isInOrOut2(n);
4438               delete pol; n->decrRef();
4439             }
4440           if(status)
4441             {
4442               eltsIndexPtr[i+1]++;
4443               elts->pushBackSilent(*iter);
4444             }
4445         }
4446     }
4447 }
4448 /*!
4449  * Finds cells in contact with several balls (i.e. points with precision).
4450  * This method is an extension of getCellContainingPoint() and
4451  * getCellsContainingPoint() for the case of multiple points.
4452  * 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.
4453  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4454  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4455  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4456  *         this->getSpaceDimension() * \a nbOfPoints 
4457  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4458  *  \param [in] eps - radius of balls (i.e. the precision).
4459  *  \param [out] elts - vector returning ids of found cells.
4460  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4461  *         dividing cell ids in \a elts into groups each referring to one
4462  *         point. Its every element (except the last one) is an index pointing to the
4463  *         first id of a group of cells. For example cells in contact with the *i*-th
4464  *         point are described by following range of indices:
4465  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4466  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4467  *         Number of cells in contact with the *i*-th point is
4468  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4469  *  \throw If the coordinates array is not set.
4470  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4471  *
4472  *  \if ENABLE_EXAMPLES
4473  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4474  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4475  *  \endif
4476  */
4477 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4478                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4479 {
4480   int spaceDim=getSpaceDimension();
4481   int mDim=getMeshDimension();
4482   if(spaceDim==3)
4483     {
4484       if(mDim==3)
4485         {
4486           const double *coords=_coords->getConstPointer();
4487           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4488         }
4489       /*else if(mDim==2)
4490         {
4491
4492         }*/
4493       else
4494         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4495     }
4496   else if(spaceDim==2)
4497     {
4498       if(mDim==2)
4499         {
4500           const double *coords=_coords->getConstPointer();
4501           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4502         }
4503       else
4504         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4505     }
4506   else if(spaceDim==1)
4507     {
4508       if(mDim==1)
4509         {
4510           const double *coords=_coords->getConstPointer();
4511           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4512         }
4513       else
4514         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4515     }
4516   else
4517     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4518 }
4519
4520 /*!
4521  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4522  * least two its edges intersect each other anywhere except their extremities. An
4523  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4524  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4525  *         cleared before filling in.
4526  *  \param [in] eps - precision.
4527  *  \throw If \a this->getMeshDimension() != 2.
4528  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4529  */
4530 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4531 {
4532   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4533   if(getMeshDimension()!=2)
4534     throw INTERP_KERNEL::Exception(msg);
4535   int spaceDim=getSpaceDimension();
4536   if(spaceDim!=2 && spaceDim!=3)
4537     throw INTERP_KERNEL::Exception(msg);
4538   const int *conn=_nodal_connec->getConstPointer();
4539   const int *connI=_nodal_connec_index->getConstPointer();
4540   int nbOfCells=getNumberOfCells();
4541   std::vector<double> cell2DinS2;
4542   for(int i=0;i<nbOfCells;i++)
4543     {
4544       int offset=connI[i];
4545       int nbOfNodesForCell=connI[i+1]-offset-1;
4546       if(nbOfNodesForCell<=3)
4547         continue;
4548       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4549       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4550       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4551         cells.push_back(i);
4552       cell2DinS2.clear();
4553     }
4554 }
4555
4556 /*!
4557  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4558  *
4559  * 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.
4560  * 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.
4561  * 
4562  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4563  * This convex envelop is computed using Jarvis march algorithm.
4564  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4565  * 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)
4566  * 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.
4567  *
4568  * \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.
4569  * \sa MEDCouplingUMesh::colinearize2D
4570  */
4571 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4572 {
4573   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4574     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4575   checkFullyDefined();
4576   const double *coords=getCoords()->getConstPointer();
4577   int nbOfCells=getNumberOfCells();
4578   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4579   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4580   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4581   int *workIndexOut=nodalConnecIndexOut->getPointer();
4582   *workIndexOut=0;
4583   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4584   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4585   std::set<INTERP_KERNEL::NormalizedCellType> types;
4586   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4587   isChanged->alloc(0,1);
4588   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4589     {
4590       int pos=nodalConnecOut->getNumberOfTuples();
4591       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4592         isChanged->pushBackSilent(i);
4593       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4594       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4595     }
4596   if(isChanged->empty())
4597     return 0;
4598   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4599   _types=types;
4600   return isChanged.retn();
4601 }
4602
4603 /*!
4604  * This method is \b NOT const because it can modify \a this.
4605  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4606  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4607  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4608  * \b 1 for translation and rotation around point of 'mesh1D'.
4609  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4610  */
4611 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4612 {
4613   checkFullyDefined();
4614   mesh1D->checkFullyDefined();
4615   if(!mesh1D->isContiguous1D())
4616     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4617   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4618     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4619   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4620     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4621   if(mesh1D->getMeshDimension()!=1)
4622     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4623   bool isQuad=false;
4624   if(isPresenceOfQuadratic())
4625     {
4626       if(mesh1D->isFullyQuadratic())
4627         isQuad=true;
4628       else
4629         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4630     }
4631   int oldNbOfNodes=getNumberOfNodes();
4632   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4633   switch(policy)
4634   {
4635     case 0:
4636       {
4637         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4638         break;
4639       }
4640     case 1:
4641       {
4642         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4643         break;
4644       }
4645     default:
4646       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4647   }
4648   setCoords(newCoords);
4649   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4650   updateTime();
4651   return ret.retn();
4652 }
4653
4654 /*!
4655  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4656  * If it is not the case an exception will be thrown.
4657  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4658  * intersection of plane defined by ('origin','vec').
4659  * This method has one in/out parameter : 'cut3DCurve'.
4660  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4661  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4662  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4663  * This method will throw an exception if \a this contains a non linear segment.
4664  */
4665 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4666 {
4667   checkFullyDefined();
4668   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4669     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4670   int ncells=getNumberOfCells();
4671   int nnodes=getNumberOfNodes();
4672   double vec2[3],vec3[3],vec4[3];
4673   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4674   if(normm<1e-6)
4675     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4676   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4677   const int *conn=_nodal_connec->getConstPointer();
4678   const int *connI=_nodal_connec_index->getConstPointer();
4679   const double *coo=_coords->getConstPointer();
4680   std::vector<double> addCoo;
4681   for(int i=0;i<ncells;i++)
4682     {
4683       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4684         {
4685           if(cut3DCurve[i]==-2)
4686             {
4687               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4688               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];
4689               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4690               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4691               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4692                 {
4693                   const double *st2=coo+3*st;
4694                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4695                   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]));
4696                   if(pos>eps && pos<1-eps)
4697                     {
4698                       int nNode=((int)addCoo.size())/3;
4699                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4700                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4701                       cut3DCurve[i]=nnodes+nNode;
4702                     }
4703                 }
4704             }
4705         }
4706       else
4707         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4708     }
4709   if(!addCoo.empty())
4710     {
4711       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4712       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4713       coo2->alloc(newNbOfNodes,3);
4714       double *tmp=coo2->getPointer();
4715       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4716       std::copy(addCoo.begin(),addCoo.end(),tmp);
4717       DataArrayDouble::SetArrayIn(coo2,_coords);
4718     }
4719 }
4720
4721 /*!
4722  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4723  * \param mesh1D is the input 1D mesh used for translation computation.
4724  * \return newCoords new coords filled by this method. 
4725  */
4726 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4727 {
4728   int oldNbOfNodes=getNumberOfNodes();
4729   int nbOf1DCells=mesh1D->getNumberOfCells();
4730   int spaceDim=getSpaceDimension();
4731   DataArrayDouble *ret=DataArrayDouble::New();
4732   std::vector<bool> isQuads;
4733   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4734   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4735   double *retPtr=ret->getPointer();
4736   const double *coords=getCoords()->getConstPointer();
4737   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4738   std::vector<int> v;
4739   std::vector<double> c;
4740   double vec[3];
4741   v.reserve(3);
4742   c.reserve(6);
4743   for(int i=0;i<nbOf1DCells;i++)
4744     {
4745       v.resize(0);
4746       mesh1D->getNodeIdsOfCell(i,v);
4747       c.resize(0);
4748       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4749       mesh1D->getCoordinatesOfNode(v[0],c);
4750       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4751       for(int j=0;j<oldNbOfNodes;j++)
4752         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4753       if(isQuad)
4754         {
4755           c.resize(0);
4756           mesh1D->getCoordinatesOfNode(v[1],c);
4757           mesh1D->getCoordinatesOfNode(v[0],c);
4758           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4759           for(int j=0;j<oldNbOfNodes;j++)
4760             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4761         }
4762     }
4763   ret->copyStringInfoFrom(*getCoords());
4764   return ret;
4765 }
4766
4767 /*!
4768  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4769  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4770  * \return newCoords new coords filled by this method. 
4771  */
4772 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4773 {
4774   if(mesh1D->getSpaceDimension()==2)
4775     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4776   if(mesh1D->getSpaceDimension()==3)
4777     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4778   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4779 }
4780
4781 /*!
4782  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4783  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4784  * \return newCoords new coords filled by this method. 
4785  */
4786 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4787 {
4788   if(isQuad)
4789     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4790   int oldNbOfNodes=getNumberOfNodes();
4791   int nbOf1DCells=mesh1D->getNumberOfCells();
4792   if(nbOf1DCells<2)
4793     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4794   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4795   int nbOfLevsInVec=nbOf1DCells+1;
4796   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4797   double *retPtr=ret->getPointer();
4798   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4799   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4800   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4801   tmp->setCoords(tmp2);
4802   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4803   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4804   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4805   for(int i=1;i<nbOfLevsInVec;i++)
4806     {
4807       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4808       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4809       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4810       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4811       tmp->translate(vec);
4812       double tmp3[2],radius,alpha,alpha0;
4813       const double *p0=i+1<nbOfLevsInVec?begin:third;
4814       const double *p1=i+1<nbOfLevsInVec?end:begin;
4815       const double *p2=i+1<nbOfLevsInVec?third:end;
4816       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4817       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]);
4818       double angle=acos(cosangle/(radius*radius));
4819       tmp->rotate(end,0,angle);
4820       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4821     }
4822   return ret.retn();
4823 }
4824
4825 /*!
4826  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4827  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4828  * \return newCoords new coords filled by this method. 
4829  */
4830 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4831 {
4832   if(isQuad)
4833     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4834   int oldNbOfNodes=getNumberOfNodes();
4835   int nbOf1DCells=mesh1D->getNumberOfCells();
4836   if(nbOf1DCells<2)
4837     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4838   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4839   int nbOfLevsInVec=nbOf1DCells+1;
4840   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4841   double *retPtr=ret->getPointer();
4842   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4843   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4844   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4845   tmp->setCoords(tmp2);
4846   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4847   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4848   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4849   for(int i=1;i<nbOfLevsInVec;i++)
4850     {
4851       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4852       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4853       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4854       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4855       tmp->translate(vec);
4856       double tmp3[2],radius,alpha,alpha0;
4857       const double *p0=i+1<nbOfLevsInVec?begin:third;
4858       const double *p1=i+1<nbOfLevsInVec?end:begin;
4859       const double *p2=i+1<nbOfLevsInVec?third:end;
4860       double vecPlane[3]={
4861         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4862         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4863         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4864       };
4865       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4866       if(norm>1.e-7)
4867         {
4868           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4869           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4870           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4871           double s2=norm2;
4872           double c2=cos(asin(s2));
4873           double m[3][3]={
4874             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4875             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4876             {-vec2[1]*s2, vec2[0]*s2, c2}
4877           };
4878           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]};
4879           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]};
4880           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]};
4881           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4882           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]);
4883           double angle=acos(cosangle/(radius*radius));
4884           tmp->rotate(end,vecPlane,angle);
4885         }
4886       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4887     }
4888   return ret.retn();
4889 }
4890
4891 /*!
4892  * This method is private because not easy to use for end user. This method is const contrary to
4893  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4894  * the coords sorted slice by slice.
4895  * \param isQuad specifies presence of quadratic cells.
4896  */
4897 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4898 {
4899   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4900   int nbOf2DCells=getNumberOfCells();
4901   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4902   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4903   const int *conn=_nodal_connec->getConstPointer();
4904   const int *connI=_nodal_connec_index->getConstPointer();
4905   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4906   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4907   newConnI->alloc(nbOf3DCells+1,1);
4908   int *newConnIPtr=newConnI->getPointer();
4909   *newConnIPtr++=0;
4910   std::vector<int> newc;
4911   for(int j=0;j<nbOf2DCells;j++)
4912     {
4913       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4914       *newConnIPtr++=(int)newc.size();
4915     }
4916   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4917   int *newConnPtr=newConn->getPointer();
4918   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4919   newConnIPtr=newConnI->getPointer();
4920   for(int iz=0;iz<nbOf1DCells;iz++)
4921     {
4922       if(iz!=0)
4923         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4924       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4925         {
4926           int icell=(int)(iter-newc.begin());
4927           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4928             {
4929               if(*iter!=-1)
4930                 *newConnPtr=(*iter)+iz*deltaPerLev;
4931               else
4932                 *newConnPtr=-1;
4933             }
4934           else
4935             *newConnPtr=(*iter);
4936         }
4937     }
4938   ret->setConnectivity(newConn,newConnI,true);
4939   ret->setCoords(getCoords());
4940   return ret;
4941 }
4942
4943 /*!
4944  * Checks if \a this mesh is constituted by only quadratic cells.
4945  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4946  *  \throw If the coordinates array is not set.
4947  *  \throw If the nodal connectivity of cells is not defined.
4948  */
4949 bool MEDCouplingUMesh::isFullyQuadratic() const
4950 {
4951   checkFullyDefined();
4952   bool ret=true;
4953   int nbOfCells=getNumberOfCells();
4954   for(int i=0;i<nbOfCells && ret;i++)
4955     {
4956       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4957       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4958       ret=cm.isQuadratic();
4959     }
4960   return ret;
4961 }
4962
4963 /*!
4964  * Checks if \a this mesh includes any quadratic cell.
4965  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4966  *  \throw If the coordinates array is not set.
4967  *  \throw If the nodal connectivity of cells is not defined.
4968  */
4969 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4970 {
4971   checkFullyDefined();
4972   bool ret=false;
4973   int nbOfCells=getNumberOfCells();
4974   for(int i=0;i<nbOfCells && !ret;i++)
4975     {
4976       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4977       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4978       ret=cm.isQuadratic();
4979     }
4980   return ret;
4981 }
4982
4983 /*!
4984  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4985  * this mesh, it remains unchanged.
4986  *  \throw If the coordinates array is not set.
4987  *  \throw If the nodal connectivity of cells is not defined.
4988  */
4989 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4990 {
4991   checkFullyDefined();
4992   int nbOfCells=getNumberOfCells();
4993   int delta=0;
4994   const int *iciptr=_nodal_connec_index->getConstPointer();
4995   for(int i=0;i<nbOfCells;i++)
4996     {
4997       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4998       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4999       if(cm.isQuadratic())
5000         {
5001           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5002           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5003           if(!cml.isDynamic())
5004             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5005           else
5006             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5007         }
5008     }
5009   if(delta==0)
5010     return ;
5011   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5012   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5013   const int *icptr=_nodal_connec->getConstPointer();
5014   newConn->alloc(getMeshLength()-delta,1);
5015   newConnI->alloc(nbOfCells+1,1);
5016   int *ocptr=newConn->getPointer();
5017   int *ociptr=newConnI->getPointer();
5018   *ociptr=0;
5019   _types.clear();
5020   for(int i=0;i<nbOfCells;i++,ociptr++)
5021     {
5022       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5023       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5024       if(!cm.isQuadratic())
5025         {
5026           _types.insert(type);
5027           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5028           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5029         }
5030       else
5031         {
5032           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5033           _types.insert(typel);
5034           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5035           int newNbOfNodes=cml.getNumberOfNodes();
5036           if(cml.isDynamic())
5037             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5038           *ocptr++=(int)typel;
5039           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5040           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5041         }
5042     }
5043   setConnectivity(newConn,newConnI,false);
5044 }
5045
5046 /*!
5047  * This method converts all linear cell in \a this to quadratic one.
5048  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5049  * 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)
5050  * 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.
5051  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5052  * end of the existing coordinates.
5053  * 
5054  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5055  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5056  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5057  * 
5058  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5059  *
5060  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5061  */
5062 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5063 {
5064   DataArrayInt *conn=0,*connI=0;
5065   DataArrayDouble *coords=0;
5066   std::set<INTERP_KERNEL::NormalizedCellType> types;
5067   checkFullyDefined();
5068   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5069   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5070   int meshDim=getMeshDimension();
5071   switch(conversionType)
5072   {
5073     case 0:
5074       switch(meshDim)
5075       {
5076         case 1:
5077           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5078           connSafe=conn; connISafe=connI; coordsSafe=coords;
5079           break;
5080         case 2:
5081           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5082           connSafe=conn; connISafe=connI; coordsSafe=coords;
5083           break;
5084         case 3:
5085           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5086           connSafe=conn; connISafe=connI; coordsSafe=coords;
5087           break;
5088         default:
5089           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5090       }
5091       break;
5092         case 1:
5093           {
5094             switch(meshDim)
5095             {
5096               case 1:
5097                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5098                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5099                 break;
5100               case 2:
5101                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5102                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5103                 break;
5104               case 3:
5105                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5106                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5107                 break;
5108               default:
5109                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5110             }
5111             break;
5112           }
5113         default:
5114           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5115   }
5116   setConnectivity(connSafe,connISafe,false);
5117   _types=types;
5118   setCoords(coordsSafe);
5119   return ret.retn();
5120 }
5121
5122 #if 0
5123 /*!
5124  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5125  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5126  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5127  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5128  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5129  * This method can be seen as the opposite method of colinearize2D.
5130  * 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
5131  * to avoid to modify the numbering of existing nodes.
5132  *
5133  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5134  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5135  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5136  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5137  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5138  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5139  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5140  *
5141  * \sa buildDescendingConnectivity2
5142  */
5143 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5144                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5145 {
5146   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5147     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5148   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5149   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5150     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5151   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5152     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5153   //DataArrayInt *out0(0),*outi0(0);
5154   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5155   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5156   //out0s=out0s->buildUnique(); out0s->sort(true);
5157 }
5158 #endif
5159
5160 /*!
5161  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5162  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5163  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5164  */
5165 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5166 {
5167   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5168   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5169   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5170   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5171   int nbOfCells=getNumberOfCells();
5172   int nbOfNodes=getNumberOfNodes();
5173   const int *cPtr=_nodal_connec->getConstPointer();
5174   const int *icPtr=_nodal_connec_index->getConstPointer();
5175   int lastVal=0,offset=nbOfNodes;
5176   for(int i=0;i<nbOfCells;i++,icPtr++)
5177     {
5178       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5179       if(type==INTERP_KERNEL::NORM_SEG2)
5180         {
5181           types.insert(INTERP_KERNEL::NORM_SEG3);
5182           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5183           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5184           newConn->pushBackSilent(offset++);
5185           lastVal+=4;
5186           newConnI->pushBackSilent(lastVal);
5187           ret->pushBackSilent(i);
5188         }
5189       else
5190         {
5191           types.insert(type);
5192           lastVal+=(icPtr[1]-icPtr[0]);
5193           newConnI->pushBackSilent(lastVal);
5194           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5195         }
5196     }
5197   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5198   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5199   return ret.retn();
5200 }
5201
5202 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
5203 {
5204   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5205   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5206   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5207   //
5208   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5209   DataArrayInt *conn1D=0,*conn1DI=0;
5210   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5211   DataArrayDouble *coordsTmp=0;
5212   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5213   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5214   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5215   const int *c1DPtr=conn1D->begin();
5216   const int *c1DIPtr=conn1DI->begin();
5217   int nbOfCells=getNumberOfCells();
5218   const int *cPtr=_nodal_connec->getConstPointer();
5219   const int *icPtr=_nodal_connec_index->getConstPointer();
5220   int lastVal=0;
5221   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5222     {
5223       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5224       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5225       if(!cm.isQuadratic())
5226         {
5227           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5228           types.insert(typ2); newConn->pushBackSilent(typ2);
5229           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5230           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5231             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5232           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5233           newConnI->pushBackSilent(lastVal);
5234           ret->pushBackSilent(i);
5235         }
5236       else
5237         {
5238           types.insert(typ);
5239           lastVal+=(icPtr[1]-icPtr[0]);
5240           newConnI->pushBackSilent(lastVal);
5241           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5242         }
5243     }
5244   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5245   return ret.retn();
5246 }
5247
5248 /*!
5249  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5250  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5251  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5252  */
5253 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5254 {
5255   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5256   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5257   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5258 }
5259
5260 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5261 {
5262   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5263   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5264   //
5265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5266   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5267   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5268   //
5269   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5270   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5271   DataArrayInt *conn1D=0,*conn1DI=0;
5272   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5273   DataArrayDouble *coordsTmp=0;
5274   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5275   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5277   const int *c1DPtr=conn1D->begin();
5278   const int *c1DIPtr=conn1DI->begin();
5279   int nbOfCells=getNumberOfCells();
5280   const int *cPtr=_nodal_connec->getConstPointer();
5281   const int *icPtr=_nodal_connec_index->getConstPointer();
5282   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5283   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5284     {
5285       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5286       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5287       if(!cm.isQuadratic())
5288         {
5289           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5290           types.insert(typ2); newConn->pushBackSilent(typ2);
5291           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5292           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5293             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5294           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5295           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5296           newConnI->pushBackSilent(lastVal);
5297           ret->pushBackSilent(i);
5298         }
5299       else
5300         {
5301           types.insert(typ);
5302           lastVal+=(icPtr[1]-icPtr[0]);
5303           newConnI->pushBackSilent(lastVal);
5304           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5305         }
5306     }
5307   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5308   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5309   return ret.retn();
5310 }
5311
5312 /*!
5313  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5314  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5315  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5316  */
5317 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5318 {
5319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5320   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5321   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5322 }
5323
5324 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5325 {
5326   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5327   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5328   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5329   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5330   //
5331   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5332   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5333   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5334   //
5335   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5336   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5337   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5338   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5339   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5340   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5341   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5342   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5344   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5345   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5346   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5347   int nbOfCells=getNumberOfCells();
5348   const int *cPtr=_nodal_connec->getConstPointer();
5349   const int *icPtr=_nodal_connec_index->getConstPointer();
5350   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5351   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5352     {
5353       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5354       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5355       if(!cm.isQuadratic())
5356         {
5357           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5358           if(typ2==INTERP_KERNEL::NORM_ERROR)
5359             {
5360               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5361               throw INTERP_KERNEL::Exception(oss.str().c_str());
5362             }
5363           types.insert(typ2); newConn->pushBackSilent(typ2);
5364           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5365           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5366             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5367           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5368             {
5369               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5370               int tmpPos=newConn->getNumberOfTuples();
5371               newConn->pushBackSilent(nodeId2);
5372               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5373             }
5374           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5375           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5376           newConnI->pushBackSilent(lastVal);
5377           ret->pushBackSilent(i);
5378         }
5379       else
5380         {
5381           types.insert(typ);
5382           lastVal+=(icPtr[1]-icPtr[0]);
5383           newConnI->pushBackSilent(lastVal);
5384           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5385         }
5386     }
5387   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5389   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5390   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5391   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5392   int *c=newConn->getPointer();
5393   const int *cI(newConnI->begin());
5394   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5395     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5396   offset=coordsTmp2Safe->getNumberOfTuples();
5397   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5398     c[cI[(*elt)+1]-1]+=offset;
5399   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5400   return ret.retn();
5401 }
5402
5403 /*!
5404  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5405  * so that the number of cells remains the same. Quadratic faces are converted to
5406  * polygons. This method works only for 2D meshes in
5407  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5408  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5409  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5410  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5411  *         a polylinized edge constituting the input polygon.
5412  *  \throw If the coordinates array is not set.
5413  *  \throw If the nodal connectivity of cells is not defined.
5414  *  \throw If \a this->getMeshDimension() != 2.
5415  *  \throw If \a this->getSpaceDimension() != 2.
5416  */
5417 void MEDCouplingUMesh::tessellate2D(double eps)
5418 {
5419   checkFullyDefined();
5420   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5421     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5422   double epsa=fabs(eps);
5423   if(epsa<std::numeric_limits<double>::min())
5424     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 !");
5425   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5426   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5427   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5428   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5429   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5430   revDesc1=0; revDescIndx1=0;
5431   mDesc->tessellate2DCurve(eps);
5432   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5433   setCoords(mDesc->getCoords());
5434 }
5435
5436 /*!
5437  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5438  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5439  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5440  *         a sub-divided edge.
5441  *  \throw If the coordinates array is not set.
5442  *  \throw If the nodal connectivity of cells is not defined.
5443  *  \throw If \a this->getMeshDimension() != 1.
5444  *  \throw If \a this->getSpaceDimension() != 2.
5445  */
5446 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5447 {
5448   checkFullyDefined();
5449   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5450     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5451   double epsa=fabs(eps);
5452   if(epsa<std::numeric_limits<double>::min())
5453     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 !");
5454   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5455   int nbCells=getNumberOfCells();
5456   int nbNodes=getNumberOfNodes();
5457   const int *conn=_nodal_connec->getConstPointer();
5458   const int *connI=_nodal_connec_index->getConstPointer();
5459   const double *coords=_coords->getConstPointer();
5460   std::vector<double> addCoo;
5461   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5463   newConnI->alloc(nbCells+1,1);
5464   int *newConnIPtr=newConnI->getPointer();
5465   *newConnIPtr=0;
5466   int tmp1[3];
5467   INTERP_KERNEL::Node *tmp2[3];
5468   std::set<INTERP_KERNEL::NormalizedCellType> types;
5469   for(int i=0;i<nbCells;i++,newConnIPtr++)
5470     {
5471       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5472       if(cm.isQuadratic())
5473         {//assert(connI[i+1]-connI[i]-1==3)
5474           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5475           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5476           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5477           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5478           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5479           if(eac)
5480             {
5481               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5482               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5483               delete eac;
5484               newConnIPtr[1]=(int)newConn.size();
5485             }
5486           else
5487             {
5488               types.insert(INTERP_KERNEL::NORM_SEG2);
5489               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5490               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5491               newConnIPtr[1]=newConnIPtr[0]+3;
5492             }
5493         }
5494       else
5495         {
5496           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5497           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5498           newConnIPtr[1]=newConnIPtr[0]+3;
5499         }
5500     }
5501   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5502     return ;
5503   _types=types;
5504   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5505   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5506   newConnArr->alloc((int)newConn.size(),1);
5507   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5508   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5509   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5510   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5511   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5512   std::copy(addCoo.begin(),addCoo.end(),work);
5513   DataArrayDouble::SetArrayIn(newCoords,_coords);
5514   updateTime();
5515 }
5516
5517 /*!
5518  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5519  * In addition, returns an array mapping new cells to old ones. <br>
5520  * This method typically increases the number of cells in \a this mesh
5521  * but the number of nodes remains \b unchanged.
5522  * That's why the 3D splitting policies
5523  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5524  *  \param [in] policy - specifies a pattern used for splitting.
5525  * The semantic of \a policy is:
5526  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5527  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5528  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5529  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5530  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5531  *          an id of old cell producing it. The caller is to delete this array using
5532  *         decrRef() as it is no more needed. 
5533  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5534  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5535  *          and \a this->getMeshDimension() != 3. 
5536  *  \throw If \a policy is not one of the four discussed above.
5537  *  \throw If the nodal connectivity of cells is not defined.
5538  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5539  */
5540 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5541 {
5542   switch(policy)
5543   {
5544     case 0:
5545       return simplexizePol0();
5546     case 1:
5547       return simplexizePol1();
5548     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5549         return simplexizePlanarFace5();
5550     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5551         return simplexizePlanarFace6();
5552     default:
5553       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)");
5554   }
5555 }
5556
5557 /*!
5558  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5559  * - 1D: INTERP_KERNEL::NORM_SEG2
5560  * - 2D: INTERP_KERNEL::NORM_TRI3
5561  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5562  *
5563  * This method is useful for users that need to use P1 field services as
5564  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5565  * All these methods need mesh support containing only simplex cells.
5566  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5567  *  \throw If the coordinates array is not set.
5568  *  \throw If the nodal connectivity of cells is not defined.
5569  *  \throw If \a this->getMeshDimension() < 1.
5570  */
5571 bool MEDCouplingUMesh::areOnlySimplexCells() const
5572 {
5573   checkFullyDefined();
5574   int mdim=getMeshDimension();
5575   if(mdim<1 || mdim>3)
5576     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5577   int nbCells=getNumberOfCells();
5578   const int *conn=_nodal_connec->getConstPointer();
5579   const int *connI=_nodal_connec_index->getConstPointer();
5580   for(int i=0;i<nbCells;i++)
5581     {
5582       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5583       if(!cm.isSimplex())
5584         return false;
5585     }
5586   return true;
5587 }
5588
5589 /*!
5590  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5591  */
5592 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5593 {
5594   checkConnectivityFullyDefined();
5595   if(getMeshDimension()!=2)
5596     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5597   int nbOfCells=getNumberOfCells();
5598   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5599   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5600   ret->alloc(nbOfCells+nbOfCutCells,1);
5601   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5602   int *retPt=ret->getPointer();
5603   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5604   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5605   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5606   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5607   int *pt=newConn->getPointer();
5608   int *ptI=newConnI->getPointer();
5609   ptI[0]=0;
5610   const int *oldc=_nodal_connec->getConstPointer();
5611   const int *ci=_nodal_connec_index->getConstPointer();
5612   for(int i=0;i<nbOfCells;i++,ci++)
5613     {
5614       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5615         {
5616           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5617             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5618           pt=std::copy(tmp,tmp+8,pt);
5619           ptI[1]=ptI[0]+4;
5620           ptI[2]=ptI[0]+8;
5621           *retPt++=i;
5622           *retPt++=i;
5623           ptI+=2;
5624         }
5625       else
5626         {
5627           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5628           ptI[1]=ptI[0]+ci[1]-ci[0];
5629           ptI++;
5630           *retPt++=i;
5631         }
5632     }
5633   _nodal_connec->decrRef();
5634   _nodal_connec=newConn.retn();
5635   _nodal_connec_index->decrRef();
5636   _nodal_connec_index=newConnI.retn();
5637   computeTypes();
5638   updateTime();
5639   return ret.retn();
5640 }
5641
5642 /*!
5643  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5644  */
5645 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5646 {
5647   checkConnectivityFullyDefined();
5648   if(getMeshDimension()!=2)
5649     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5650   int nbOfCells=getNumberOfCells();
5651   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5652   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5653   ret->alloc(nbOfCells+nbOfCutCells,1);
5654   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5655   int *retPt=ret->getPointer();
5656   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5657   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5658   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5659   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5660   int *pt=newConn->getPointer();
5661   int *ptI=newConnI->getPointer();
5662   ptI[0]=0;
5663   const int *oldc=_nodal_connec->getConstPointer();
5664   const int *ci=_nodal_connec_index->getConstPointer();
5665   for(int i=0;i<nbOfCells;i++,ci++)
5666     {
5667       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5668         {
5669           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5670             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5671           pt=std::copy(tmp,tmp+8,pt);
5672           ptI[1]=ptI[0]+4;
5673           ptI[2]=ptI[0]+8;
5674           *retPt++=i;
5675           *retPt++=i;
5676           ptI+=2;
5677         }
5678       else
5679         {
5680           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5681           ptI[1]=ptI[0]+ci[1]-ci[0];
5682           ptI++;
5683           *retPt++=i;
5684         }
5685     }
5686   _nodal_connec->decrRef();
5687   _nodal_connec=newConn.retn();
5688   _nodal_connec_index->decrRef();
5689   _nodal_connec_index=newConnI.retn();
5690   computeTypes();
5691   updateTime();
5692   return ret.retn();
5693 }
5694
5695 /*!
5696  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5697  */
5698 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5699 {
5700   checkConnectivityFullyDefined();
5701   if(getMeshDimension()!=3)
5702     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5703   int nbOfCells=getNumberOfCells();
5704   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5705   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5706   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5707   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5708   int *retPt=ret->getPointer();
5709   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5710   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5711   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5712   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5713   int *pt=newConn->getPointer();
5714   int *ptI=newConnI->getPointer();
5715   ptI[0]=0;
5716   const int *oldc=_nodal_connec->getConstPointer();
5717   const int *ci=_nodal_connec_index->getConstPointer();
5718   for(int i=0;i<nbOfCells;i++,ci++)
5719     {
5720       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5721         {
5722           for(int j=0;j<5;j++,pt+=5,ptI++)
5723             {
5724               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5725               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];
5726               *retPt++=i;
5727               ptI[1]=ptI[0]+5;
5728             }
5729         }
5730       else
5731         {
5732           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5733           ptI[1]=ptI[0]+ci[1]-ci[0];
5734           ptI++;
5735           *retPt++=i;
5736         }
5737     }
5738   _nodal_connec->decrRef();
5739   _nodal_connec=newConn.retn();
5740   _nodal_connec_index->decrRef();
5741   _nodal_connec_index=newConnI.retn();
5742   computeTypes();
5743   updateTime();
5744   return ret.retn();
5745 }
5746
5747 /*!
5748  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5749  */
5750 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5751 {
5752   checkConnectivityFullyDefined();
5753   if(getMeshDimension()!=3)
5754     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5755   int nbOfCells=getNumberOfCells();
5756   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5757   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5758   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5759   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5760   int *retPt=ret->getPointer();
5761   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5762   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5763   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5764   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5765   int *pt=newConn->getPointer();
5766   int *ptI=newConnI->getPointer();
5767   ptI[0]=0;
5768   const int *oldc=_nodal_connec->getConstPointer();
5769   const int *ci=_nodal_connec_index->getConstPointer();
5770   for(int i=0;i<nbOfCells;i++,ci++)
5771     {
5772       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5773         {
5774           for(int j=0;j<6;j++,pt+=5,ptI++)
5775             {
5776               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5777               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];
5778               *retPt++=i;
5779               ptI[1]=ptI[0]+5;
5780             }
5781         }
5782       else
5783         {
5784           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5785           ptI[1]=ptI[0]+ci[1]-ci[0];
5786           ptI++;
5787           *retPt++=i;
5788         }
5789     }
5790   _nodal_connec->decrRef();
5791   _nodal_connec=newConn.retn();
5792   _nodal_connec_index->decrRef();
5793   _nodal_connec_index=newConnI.retn();
5794   computeTypes();
5795   updateTime();
5796   return ret.retn();
5797 }
5798
5799 /*!
5800  * 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.
5801  * This method completly ignore coordinates.
5802  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5803  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5804  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5805  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5806  */
5807 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5808 {
5809   checkFullyDefined();
5810   if(getMeshDimension()!=2)
5811     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5812   int nbOfCells=getNumberOfCells();
5813   int *connI=_nodal_connec_index->getPointer();
5814   int newConnLgth=0;
5815   for(int i=0;i<nbOfCells;i++,connI++)
5816     {
5817       int offset=descIndex[i];
5818       int nbOfEdges=descIndex[i+1]-offset;
5819       //
5820       bool ddirect=desc[offset+nbOfEdges-1]>0;
5821       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5822       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5823       for(int j=0;j<nbOfEdges;j++)
5824         {
5825           bool direct=desc[offset+j]>0;
5826           int edgeId=std::abs(desc[offset+j])-1;
5827           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5828             {
5829               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5830               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5831               int ref2=direct?id1:id2;
5832               if(ref==ref2)
5833                 {
5834                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5835                   newConnLgth+=nbOfSubNodes-1;
5836                   ref=direct?id2:id1;
5837                 }
5838               else
5839                 {
5840                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5841                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5842                 }
5843             }
5844           else
5845             {
5846               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5847             }
5848         }
5849       newConnLgth++;//+1 is for cell type
5850       connI[1]=newConnLgth;
5851     }
5852   //
5853   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5854   newConn->alloc(newConnLgth,1);
5855   int *work=newConn->getPointer();
5856   for(int i=0;i<nbOfCells;i++)
5857     {
5858       *work++=INTERP_KERNEL::NORM_POLYGON;
5859       int offset=descIndex[i];
5860       int nbOfEdges=descIndex[i+1]-offset;
5861       for(int j=0;j<nbOfEdges;j++)
5862         {
5863           bool direct=desc[offset+j]>0;
5864           int edgeId=std::abs(desc[offset+j])-1;
5865           if(direct)
5866             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5867           else
5868             {
5869               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5870               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5871               work=std::copy(it,it+nbOfSubNodes-1,work);
5872             }
5873         }
5874     }
5875   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5876   _types.clear();
5877   if(nbOfCells>0)
5878     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5879 }
5880
5881 /*!
5882  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5883  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5884  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5885  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5886  * so it can be useful to call mergeNodes() before calling this method.
5887  *  \throw If \a this->getMeshDimension() <= 1.
5888  *  \throw If the coordinates array is not set.
5889  *  \throw If the nodal connectivity of cells is not defined.
5890  */
5891 void MEDCouplingUMesh::convertDegeneratedCells()
5892 {
5893   checkFullyDefined();
5894   if(getMeshDimension()<=1)
5895     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5896   int nbOfCells=getNumberOfCells();
5897   if(nbOfCells<1)
5898     return ;
5899   int initMeshLgth=getMeshLength();
5900   int *conn=_nodal_connec->getPointer();
5901   int *index=_nodal_connec_index->getPointer();
5902   int posOfCurCell=0;
5903   int newPos=0;
5904   int lgthOfCurCell;
5905   for(int i=0;i<nbOfCells;i++)
5906     {
5907       lgthOfCurCell=index[i+1]-posOfCurCell;
5908       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5909       int newLgth;
5910       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5911                                                                                                      conn+newPos+1,newLgth);
5912       conn[newPos]=newType;
5913       newPos+=newLgth+1;
5914       posOfCurCell=index[i+1];
5915       index[i+1]=newPos;
5916     }
5917   if(newPos!=initMeshLgth)
5918     _nodal_connec->reAlloc(newPos);
5919   computeTypes();
5920 }
5921
5922 /*!
5923  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5924  * A cell is considered to be oriented correctly if an angle between its
5925  * normal vector and a given vector is less than \c PI / \c 2.
5926  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5927  *         cells. 
5928  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5929  *         checked.
5930  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5931  *         is not cleared before filling in.
5932  *  \throw If \a this->getMeshDimension() != 2.
5933  *  \throw If \a this->getSpaceDimension() != 3.
5934  *
5935  *  \if ENABLE_EXAMPLES
5936  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5937  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5938  *  \endif
5939  */
5940 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5941 {
5942   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5943     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5944   int nbOfCells=getNumberOfCells();
5945   const int *conn=_nodal_connec->getConstPointer();
5946   const int *connI=_nodal_connec_index->getConstPointer();
5947   const double *coordsPtr=_coords->getConstPointer();
5948   for(int i=0;i<nbOfCells;i++)
5949     {
5950       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5951       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5952         {
5953           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5954           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5955             cells.push_back(i);
5956         }
5957     }
5958 }
5959
5960 /*!
5961  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5962  * considered to be oriented correctly if an angle between its normal vector and a
5963  * given vector is less than \c PI / \c 2. 
5964  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5965  *         cells. 
5966  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5967  *         checked.
5968  *  \throw If \a this->getMeshDimension() != 2.
5969  *  \throw If \a this->getSpaceDimension() != 3.
5970  *
5971  *  \if ENABLE_EXAMPLES
5972  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5973  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5974  *  \endif
5975  *
5976  *  \sa changeOrientationOfCells
5977  */
5978 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5979 {
5980   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5981     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5982   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
5983   const int *connI(_nodal_connec_index->getConstPointer());
5984   const double *coordsPtr(_coords->getConstPointer());
5985   bool isModified(false);
5986   for(int i=0;i<nbOfCells;i++)
5987     {
5988       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5989       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5990         {
5991           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
5992           bool isQuadratic(cm.isQuadratic());
5993           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5994             {
5995               isModified=true;
5996               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
5997             }
5998         }
5999     }
6000   if(isModified)
6001     _nodal_connec->declareAsNew();
6002   updateTime();
6003 }
6004
6005 /*!
6006  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6007  *
6008  * \sa orientCorrectly2DCells
6009  */
6010 void MEDCouplingUMesh::changeOrientationOfCells()
6011 {
6012   int mdim(getMeshDimension());
6013   if(mdim!=2 && mdim!=1)
6014     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6015   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6016   const int *connI(_nodal_connec_index->getConstPointer());
6017   if(mdim==2)
6018     {//2D
6019       for(int i=0;i<nbOfCells;i++)
6020         {
6021           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6022           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6023           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6024         }
6025     }
6026   else
6027     {//1D
6028       for(int i=0;i<nbOfCells;i++)
6029         {
6030           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6031           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6032           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6033         }
6034     }
6035 }
6036
6037 /*!
6038  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6039  * oriented facets. The normal vector of the facet should point out of the cell.
6040  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6041  *         is not cleared before filling in.
6042  *  \throw If \a this->getMeshDimension() != 3.
6043  *  \throw If \a this->getSpaceDimension() != 3.
6044  *  \throw If the coordinates array is not set.
6045  *  \throw If the nodal connectivity of cells is not defined.
6046  *
6047  *  \if ENABLE_EXAMPLES
6048  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6049  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6050  *  \endif
6051  */
6052 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6053 {
6054   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6055     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6056   int nbOfCells=getNumberOfCells();
6057   const int *conn=_nodal_connec->getConstPointer();
6058   const int *connI=_nodal_connec_index->getConstPointer();
6059   const double *coordsPtr=_coords->getConstPointer();
6060   for(int i=0;i<nbOfCells;i++)
6061     {
6062       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6063       if(type==INTERP_KERNEL::NORM_POLYHED)
6064         {
6065           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6066             cells.push_back(i);
6067         }
6068     }
6069 }
6070
6071 /*!
6072  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6073  * out of the cell. 
6074  *  \throw If \a this->getMeshDimension() != 3.
6075  *  \throw If \a this->getSpaceDimension() != 3.
6076  *  \throw If the coordinates array is not set.
6077  *  \throw If the nodal connectivity of cells is not defined.
6078  *  \throw If the reparation fails.
6079  *
6080  *  \if ENABLE_EXAMPLES
6081  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6082  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6083  *  \endif
6084  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6085  */
6086 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6087 {
6088   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6089     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6090   int nbOfCells=getNumberOfCells();
6091   int *conn=_nodal_connec->getPointer();
6092   const int *connI=_nodal_connec_index->getConstPointer();
6093   const double *coordsPtr=_coords->getConstPointer();
6094   for(int i=0;i<nbOfCells;i++)
6095     {
6096       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6097       if(type==INTERP_KERNEL::NORM_POLYHED)
6098         {
6099           try
6100           {
6101               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6102                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6103           }
6104           catch(INTERP_KERNEL::Exception& e)
6105           {
6106               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6107               throw INTERP_KERNEL::Exception(oss.str().c_str());
6108           }
6109         }
6110     }
6111   updateTime();
6112 }
6113
6114 /*!
6115  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6116  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6117  * according to which the first facet of the cell should be oriented to have the normal vector
6118  * pointing out of cell.
6119  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6120  *         cells. The caller is to delete this array using decrRef() as it is no more
6121  *         needed. 
6122  *  \throw If \a this->getMeshDimension() != 3.
6123  *  \throw If \a this->getSpaceDimension() != 3.
6124  *  \throw If the coordinates array is not set.
6125  *  \throw If the nodal connectivity of cells is not defined.
6126  *
6127  *  \if ENABLE_EXAMPLES
6128  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6129  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6130  *  \endif
6131  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6132  */
6133 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6134 {
6135   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6136   if(getMeshDimension()!=3)
6137     throw INTERP_KERNEL::Exception(msg);
6138   int spaceDim=getSpaceDimension();
6139   if(spaceDim!=3)
6140     throw INTERP_KERNEL::Exception(msg);
6141   //
6142   int nbOfCells=getNumberOfCells();
6143   int *conn=_nodal_connec->getPointer();
6144   const int *connI=_nodal_connec_index->getConstPointer();
6145   const double *coo=getCoords()->getConstPointer();
6146   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6147   for(int i=0;i<nbOfCells;i++)
6148     {
6149       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6150       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6151         {
6152           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6153             {
6154               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6155               cells->pushBackSilent(i);
6156             }
6157         }
6158     }
6159   return cells.retn();
6160 }
6161
6162 /*!
6163  * This method is a faster method to correct orientation of all 3D cells in \a this.
6164  * 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.
6165  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6166  * 
6167  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6168  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6169  */
6170 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6171 {
6172   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6173     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6174   int nbOfCells=getNumberOfCells();
6175   int *conn=_nodal_connec->getPointer();
6176   const int *connI=_nodal_connec_index->getConstPointer();
6177   const double *coordsPtr=_coords->getConstPointer();
6178   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6179   for(int i=0;i<nbOfCells;i++)
6180     {
6181       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6182       switch(type)
6183       {
6184         case INTERP_KERNEL::NORM_TETRA4:
6185           {
6186             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6187               {
6188                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6189                 ret->pushBackSilent(i);
6190               }
6191             break;
6192           }
6193         case INTERP_KERNEL::NORM_PYRA5:
6194           {
6195             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6196               {
6197                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6198                 ret->pushBackSilent(i);
6199               }
6200             break;
6201           }
6202         case INTERP_KERNEL::NORM_PENTA6:
6203         case INTERP_KERNEL::NORM_HEXA8:
6204         case INTERP_KERNEL::NORM_HEXGP12:
6205           {
6206             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6207               {
6208                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6209                 ret->pushBackSilent(i);
6210               }
6211             break;
6212           }
6213         case INTERP_KERNEL::NORM_POLYHED:
6214           {
6215             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6216               {
6217                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6218                 ret->pushBackSilent(i);
6219               }
6220             break;
6221           }
6222         default:
6223           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 !");
6224       }
6225     }
6226   updateTime();
6227   return ret.retn();
6228 }
6229
6230 /*!
6231  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6232  * If it is not the case an exception will be thrown.
6233  * This method is fast because the first cell of \a this is used to compute the plane.
6234  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6235  * \param pos output of size at least 3 used to store a point owned of searched plane.
6236  */
6237 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6238 {
6239   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6240     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6241   const int *conn=_nodal_connec->getConstPointer();
6242   const int *connI=_nodal_connec_index->getConstPointer();
6243   const double *coordsPtr=_coords->getConstPointer();
6244   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6245   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6246 }
6247
6248 /*!
6249  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6250  * cells. Currently cells of the following types are treated:
6251  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6252  * For a cell of other type an exception is thrown.
6253  * Space dimension of a 2D mesh can be either 2 or 3.
6254  * The Edge Ratio of a cell \f$t\f$ is: 
6255  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6256  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6257  *  the smallest edge lengths of \f$t\f$.
6258  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6259  *          cells and one time, lying on \a this mesh. The caller is to delete this
6260  *          field using decrRef() as it is no more needed. 
6261  *  \throw If the coordinates array is not set.
6262  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6263  *  \throw If the connectivity data array has more than one component.
6264  *  \throw If the connectivity data array has a named component.
6265  *  \throw If the connectivity index data array has more than one component.
6266  *  \throw If the connectivity index data array has a named component.
6267  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6268  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6269  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6270  */
6271 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6272 {
6273   checkCoherency();
6274   int spaceDim=getSpaceDimension();
6275   int meshDim=getMeshDimension();
6276   if(spaceDim!=2 && spaceDim!=3)
6277     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6278   if(meshDim!=2 && meshDim!=3)
6279     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6280   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6281   ret->setMesh(this);
6282   int nbOfCells=getNumberOfCells();
6283   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6284   arr->alloc(nbOfCells,1);
6285   double *pt=arr->getPointer();
6286   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6287   const int *conn=_nodal_connec->getConstPointer();
6288   const int *connI=_nodal_connec_index->getConstPointer();
6289   const double *coo=_coords->getConstPointer();
6290   double tmp[12];
6291   for(int i=0;i<nbOfCells;i++,pt++)
6292     {
6293       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6294       switch(t)
6295       {
6296         case INTERP_KERNEL::NORM_TRI3:
6297           {
6298             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6299             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6300             break;
6301           }
6302         case INTERP_KERNEL::NORM_QUAD4:
6303           {
6304             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6305             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6306             break;
6307           }
6308         case INTERP_KERNEL::NORM_TETRA4:
6309           {
6310             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6311             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6312             break;
6313           }
6314         default:
6315           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6316       }
6317       conn+=connI[i+1]-connI[i];
6318     }
6319   ret->setName("EdgeRatio");
6320   ret->synchronizeTimeWithSupport();
6321   return ret.retn();
6322 }
6323
6324 /*!
6325  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6326  * cells. Currently cells of the following types are treated:
6327  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6328  * For a cell of other type an exception is thrown.
6329  * Space dimension of a 2D mesh can be either 2 or 3.
6330  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6331  *          cells and one time, lying on \a this mesh. The caller is to delete this
6332  *          field using decrRef() as it is no more needed. 
6333  *  \throw If the coordinates array is not set.
6334  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6335  *  \throw If the connectivity data array has more than one component.
6336  *  \throw If the connectivity data array has a named component.
6337  *  \throw If the connectivity index data array has more than one component.
6338  *  \throw If the connectivity index data array has a named component.
6339  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6340  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6341  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6342  */
6343 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6344 {
6345   checkCoherency();
6346   int spaceDim=getSpaceDimension();
6347   int meshDim=getMeshDimension();
6348   if(spaceDim!=2 && spaceDim!=3)
6349     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6350   if(meshDim!=2 && meshDim!=3)
6351     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6352   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6353   ret->setMesh(this);
6354   int nbOfCells=getNumberOfCells();
6355   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6356   arr->alloc(nbOfCells,1);
6357   double *pt=arr->getPointer();
6358   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6359   const int *conn=_nodal_connec->getConstPointer();
6360   const int *connI=_nodal_connec_index->getConstPointer();
6361   const double *coo=_coords->getConstPointer();
6362   double tmp[12];
6363   for(int i=0;i<nbOfCells;i++,pt++)
6364     {
6365       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6366       switch(t)
6367       {
6368         case INTERP_KERNEL::NORM_TRI3:
6369           {
6370             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6371             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6372             break;
6373           }
6374         case INTERP_KERNEL::NORM_QUAD4:
6375           {
6376             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6377             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6378             break;
6379           }
6380         case INTERP_KERNEL::NORM_TETRA4:
6381           {
6382             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6383             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6384             break;
6385           }
6386         default:
6387           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6388       }
6389       conn+=connI[i+1]-connI[i];
6390     }
6391   ret->setName("AspectRatio");
6392   ret->synchronizeTimeWithSupport();
6393   return ret.retn();
6394 }
6395
6396 /*!
6397  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6398  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6399  * treated: INTERP_KERNEL::NORM_QUAD4.
6400  * For a cell of other type an exception is thrown.
6401  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6402  *          cells and one time, lying on \a this mesh. The caller is to delete this
6403  *          field using decrRef() as it is no more needed. 
6404  *  \throw If the coordinates array is not set.
6405  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6406  *  \throw If the connectivity data array has more than one component.
6407  *  \throw If the connectivity data array has a named component.
6408  *  \throw If the connectivity index data array has more than one component.
6409  *  \throw If the connectivity index data array has a named component.
6410  *  \throw If \a this->getMeshDimension() != 2.
6411  *  \throw If \a this->getSpaceDimension() != 3.
6412  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6413  */
6414 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6415 {
6416   checkCoherency();
6417   int spaceDim=getSpaceDimension();
6418   int meshDim=getMeshDimension();
6419   if(spaceDim!=3)
6420     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6421   if(meshDim!=2)
6422     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6423   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6424   ret->setMesh(this);
6425   int nbOfCells=getNumberOfCells();
6426   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6427   arr->alloc(nbOfCells,1);
6428   double *pt=arr->getPointer();
6429   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6430   const int *conn=_nodal_connec->getConstPointer();
6431   const int *connI=_nodal_connec_index->getConstPointer();
6432   const double *coo=_coords->getConstPointer();
6433   double tmp[12];
6434   for(int i=0;i<nbOfCells;i++,pt++)
6435     {
6436       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6437       switch(t)
6438       {
6439         case INTERP_KERNEL::NORM_QUAD4:
6440           {
6441             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6442             *pt=INTERP_KERNEL::quadWarp(tmp);
6443             break;
6444           }
6445         default:
6446           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6447       }
6448       conn+=connI[i+1]-connI[i];
6449     }
6450   ret->setName("Warp");
6451   ret->synchronizeTimeWithSupport();
6452   return ret.retn();
6453 }
6454
6455
6456 /*!
6457  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6458  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6459  * treated: INTERP_KERNEL::NORM_QUAD4.
6460  * For a cell of other type an exception is thrown.
6461  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6462  *          cells and one time, lying on \a this mesh. The caller is to delete this
6463  *          field using decrRef() as it is no more needed. 
6464  *  \throw If the coordinates array is not set.
6465  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6466  *  \throw If the connectivity data array has more than one component.
6467  *  \throw If the connectivity data array has a named component.
6468  *  \throw If the connectivity index data array has more than one component.
6469  *  \throw If the connectivity index data array has a named component.
6470  *  \throw If \a this->getMeshDimension() != 2.
6471  *  \throw If \a this->getSpaceDimension() != 3.
6472  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6473  */
6474 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6475 {
6476   checkCoherency();
6477   int spaceDim=getSpaceDimension();
6478   int meshDim=getMeshDimension();
6479   if(spaceDim!=3)
6480     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6481   if(meshDim!=2)
6482     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6483   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6484   ret->setMesh(this);
6485   int nbOfCells=getNumberOfCells();
6486   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6487   arr->alloc(nbOfCells,1);
6488   double *pt=arr->getPointer();
6489   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6490   const int *conn=_nodal_connec->getConstPointer();
6491   const int *connI=_nodal_connec_index->getConstPointer();
6492   const double *coo=_coords->getConstPointer();
6493   double tmp[12];
6494   for(int i=0;i<nbOfCells;i++,pt++)
6495     {
6496       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6497       switch(t)
6498       {
6499         case INTERP_KERNEL::NORM_QUAD4:
6500           {
6501             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6502             *pt=INTERP_KERNEL::quadSkew(tmp);
6503             break;
6504           }
6505         default:
6506           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6507       }
6508       conn+=connI[i+1]-connI[i];
6509     }
6510   ret->setName("Skew");
6511   ret->synchronizeTimeWithSupport();
6512   return ret.retn();
6513 }
6514
6515 /*!
6516  * This method aggregate the bbox of each cell and put it into bbox parameter.
6517  * 
6518  * \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)
6519  *                         For all other cases this input parameter is ignored.
6520  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6521  * 
6522  * \throw If \a this is not fully set (coordinates and connectivity).
6523  * \throw If a cell in \a this has no valid nodeId.
6524  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6525  */
6526 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6527 {
6528   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6529   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.
6530     return getBoundingBoxForBBTreeFast();
6531   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6532     {
6533       bool presenceOfQuadratic(false);
6534       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6535         {
6536           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6537           if(cm.isQuadratic())
6538             presenceOfQuadratic=true;
6539         }
6540       if(!presenceOfQuadratic)
6541         return getBoundingBoxForBBTreeFast();
6542       if(mDim==2 && sDim==2)
6543         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6544       else
6545         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6546     }
6547   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) !");
6548 }
6549
6550 /*!
6551  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6552  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6553  * 
6554  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6555  * 
6556  * \throw If \a this is not fully set (coordinates and connectivity).
6557  * \throw If a cell in \a this has no valid nodeId.
6558  */
6559 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6560 {
6561   checkFullyDefined();
6562   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6563   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6564   double *bbox(ret->getPointer());
6565   for(int i=0;i<nbOfCells*spaceDim;i++)
6566     {
6567       bbox[2*i]=std::numeric_limits<double>::max();
6568       bbox[2*i+1]=-std::numeric_limits<double>::max();
6569     }
6570   const double *coordsPtr(_coords->getConstPointer());
6571   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6572   for(int i=0;i<nbOfCells;i++)
6573     {
6574       int offset=connI[i]+1;
6575       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6576       for(int j=0;j<nbOfNodesForCell;j++)
6577         {
6578           int nodeId=conn[offset+j];
6579           if(nodeId>=0 && nodeId<nbOfNodes)
6580             {
6581               for(int k=0;k<spaceDim;k++)
6582                 {
6583                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6584                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6585                 }
6586               kk++;
6587             }
6588         }
6589       if(kk==0)
6590         {
6591           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6592           throw INTERP_KERNEL::Exception(oss.str().c_str());
6593         }
6594     }
6595   return ret.retn();
6596 }
6597
6598 /*!
6599  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6600  * useful for 2D meshes having quadratic cells
6601  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6602  * the two extremities of the arc of circle).
6603  * 
6604  * \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)
6605  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6606  * \throw If \a this is not fully defined.
6607  * \throw If \a this is not a mesh with meshDimension equal to 2.
6608  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6609  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6610  */
6611 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6612 {
6613   checkFullyDefined();
6614   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6615   if(spaceDim!=2 || mDim!=2)
6616     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!");
6617   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6618   double *bbox(ret->getPointer());
6619   const double *coords(_coords->getConstPointer());
6620   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6621   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6622     {
6623       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6624       int sz(connI[1]-connI[0]-1);
6625       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6626       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6627       INTERP_KERNEL::QuadraticPolygon *pol(0);
6628       for(int j=0;j<sz;j++)
6629         {
6630           int nodeId(conn[*connI+1+j]);
6631           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6632         }
6633       if(!cm.isQuadratic())
6634         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6635       else
6636         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6637       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6638       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6639     }
6640   return ret.retn();
6641 }
6642
6643 /*!
6644  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6645  * useful for 2D meshes having quadratic cells
6646  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6647  * the two extremities of the arc of circle).
6648  * 
6649  * \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)
6650  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6651  * \throw If \a this is not fully defined.
6652  * \throw If \a this is not a mesh with meshDimension equal to 1.
6653  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6654  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6655  */
6656 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6657 {
6658   checkFullyDefined();
6659   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6660   if(spaceDim!=2 || mDim!=1)
6661     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!");
6662   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6663   double *bbox(ret->getPointer());
6664   const double *coords(_coords->getConstPointer());
6665   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6666   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6667     {
6668       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6669       int sz(connI[1]-connI[0]-1);
6670       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6671       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6672       INTERP_KERNEL::Edge *edge(0);
6673       for(int j=0;j<sz;j++)
6674         {
6675           int nodeId(conn[*connI+1+j]);
6676           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6677         }
6678       if(!cm.isQuadratic())
6679         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6680       else
6681         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6682       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6683       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6684     }
6685   return ret.retn();
6686 }
6687
6688 /// @cond INTERNAL
6689
6690 namespace ParaMEDMEMImpl
6691 {
6692   class ConnReader
6693   {
6694   public:
6695     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6696     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6697   private:
6698     const int *_conn;
6699     int _val;
6700   };
6701
6702   class ConnReader2
6703   {
6704   public:
6705     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6706     bool operator() (const int& pos) { return _conn[pos]==_val; }
6707   private:
6708     const int *_conn;
6709     int _val;
6710   };
6711 }
6712
6713 /// @endcond
6714
6715 /*!
6716  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6717  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6718  * \a this is composed in cell types.
6719  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6720  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6721  * This parameter is kept only for compatibility with other methode listed above.
6722  */
6723 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6724 {
6725   checkConnectivityFullyDefined();
6726   const int *conn=_nodal_connec->getConstPointer();
6727   const int *connI=_nodal_connec_index->getConstPointer();
6728   const int *work=connI;
6729   int nbOfCells=getNumberOfCells();
6730   std::size_t n=getAllGeoTypes().size();
6731   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6732   std::set<INTERP_KERNEL::NormalizedCellType> types;
6733   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6734     {
6735       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6736       if(types.find(typ)!=types.end())
6737         {
6738           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6739           oss << " is not contiguous !";
6740           throw INTERP_KERNEL::Exception(oss.str().c_str());
6741         }
6742       types.insert(typ);
6743       ret[3*i]=typ;
6744       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6745       ret[3*i+1]=(int)std::distance(work,work2);
6746       work=work2;
6747     }
6748   return ret;
6749 }
6750
6751 /*!
6752  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6753  * only for types cell, type node is not managed.
6754  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6755  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6756  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6757  * If 2 or more same geometric type is in \a code and exception is thrown too.
6758  *
6759  * This method firstly checks
6760  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6761  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6762  * an exception is thrown too.
6763  * 
6764  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6765  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6766  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6767  */
6768 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6769 {
6770   if(code.empty())
6771     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6772   std::size_t sz=code.size();
6773   std::size_t n=sz/3;
6774   if(sz%3!=0)
6775     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6776   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6777   int nb=0;
6778   bool isNoPflUsed=true;
6779   for(std::size_t i=0;i<n;i++)
6780     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6781       {
6782         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6783         nb+=code[3*i+1];
6784         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6785           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6786         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6787       }
6788   if(types.size()!=n)
6789     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6790   if(isNoPflUsed)
6791     {
6792       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6793         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6794       if(types.size()==_types.size())
6795         return 0;
6796     }
6797   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6798   ret->alloc(nb,1);
6799   int *retPtr=ret->getPointer();
6800   const int *connI=_nodal_connec_index->getConstPointer();
6801   const int *conn=_nodal_connec->getConstPointer();
6802   int nbOfCells=getNumberOfCells();
6803   const int *i=connI;
6804   int kk=0;
6805   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6806     {
6807       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6808       int offset=(int)std::distance(connI,i);
6809       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6810       int nbOfCellsOfCurType=(int)std::distance(i,j);
6811       if(code[3*kk+2]==-1)
6812         for(int k=0;k<nbOfCellsOfCurType;k++)
6813           *retPtr++=k+offset;
6814       else
6815         {
6816           int idInIdsPerType=code[3*kk+2];
6817           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6818             {
6819               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6820               if(zePfl)
6821                 {
6822                   zePfl->checkAllocated();
6823                   if(zePfl->getNumberOfComponents()==1)
6824                     {
6825                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6826                         {
6827                           if(*k>=0 && *k<nbOfCellsOfCurType)
6828                             *retPtr=(*k)+offset;
6829                           else
6830                             {
6831                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6832                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6833                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6834                             }
6835                         }
6836                     }
6837                   else
6838                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6839                 }
6840               else
6841                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6842             }
6843           else
6844             {
6845               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6846               oss << " should be in [0," << idsPerType.size() << ") !";
6847               throw INTERP_KERNEL::Exception(oss.str().c_str());
6848             }
6849         }
6850       i=j;
6851     }
6852   return ret.retn();
6853 }
6854
6855 /*!
6856  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6857  * 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.
6858  * 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.
6859  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6860  * 
6861  * \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.
6862  * \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,
6863  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6864  * \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.
6865  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6866  * \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
6867  */
6868 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6869 {
6870   if(!profile)
6871     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6872   if(profile->getNumberOfComponents()!=1)
6873     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6874   checkConnectivityFullyDefined();
6875   const int *conn=_nodal_connec->getConstPointer();
6876   const int *connI=_nodal_connec_index->getConstPointer();
6877   int nbOfCells=getNumberOfCells();
6878   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6879   std::vector<int> typeRangeVals(1);
6880   for(const int *i=connI;i!=connI+nbOfCells;)
6881     {
6882       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6883       if(std::find(types.begin(),types.end(),curType)!=types.end())
6884         {
6885           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6886         }
6887       types.push_back(curType);
6888       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6889       typeRangeVals.push_back((int)std::distance(connI,i));
6890     }
6891   //
6892   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6893   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6894   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6895   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6896   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6897   //
6898   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6899   code.resize(3*nbOfCastsFinal);
6900   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6901   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6902   for(int i=0;i<nbOfCastsFinal;i++)
6903     {
6904       int castId=castsPresent->getIJ(i,0);
6905       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6906       idsInPflPerType2.push_back(tmp3);
6907       code[3*i]=(int)types[castId];
6908       code[3*i+1]=tmp3->getNumberOfTuples();
6909       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6910       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6911         {
6912           tmp4->copyStringInfoFrom(*profile);
6913           idsPerType2.push_back(tmp4);
6914           code[3*i+2]=(int)idsPerType2.size()-1;
6915         }
6916       else
6917         {
6918           code[3*i+2]=-1;
6919         }
6920     }
6921   std::size_t sz2=idsInPflPerType2.size();
6922   idsInPflPerType.resize(sz2);
6923   for(std::size_t i=0;i<sz2;i++)
6924     {
6925       DataArrayInt *locDa=idsInPflPerType2[i];
6926       locDa->incrRef();
6927       idsInPflPerType[i]=locDa;
6928     }
6929   std::size_t sz=idsPerType2.size();
6930   idsPerType.resize(sz);
6931   for(std::size_t i=0;i<sz;i++)
6932     {
6933       DataArrayInt *locDa=idsPerType2[i];
6934       locDa->incrRef();
6935       idsPerType[i]=locDa;
6936     }
6937 }
6938
6939 /*!
6940  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6941  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6942  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6943  * 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.
6944  */
6945 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6946 {
6947   checkFullyDefined();
6948   nM1LevMesh->checkFullyDefined();
6949   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6950     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6951   if(_coords!=nM1LevMesh->getCoords())
6952     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6953   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6954   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6955   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6956   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6957   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6958   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6959   tmp->setConnectivity(tmp0,tmp1);
6960   tmp->renumberCells(ret0->getConstPointer(),false);
6961   revDesc=tmp->getNodalConnectivity();
6962   revDescIndx=tmp->getNodalConnectivityIndex();
6963   DataArrayInt *ret=0;
6964   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6965     {
6966       int tmp2;
6967       ret->getMaxValue(tmp2);
6968       ret->decrRef();
6969       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6970       throw INTERP_KERNEL::Exception(oss.str().c_str());
6971     }
6972   nM1LevMeshIds=ret;
6973   //
6974   revDesc->incrRef();
6975   revDescIndx->incrRef();
6976   ret1->incrRef();
6977   ret0->incrRef();
6978   meshnM1Old2New=ret0;
6979   return ret1;
6980 }
6981
6982 /*!
6983  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6984  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6985  * in "Old to New" mode.
6986  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6987  *          this array using decrRef() as it is no more needed.
6988  *  \throw If the nodal connectivity of cells is not defined.
6989  */
6990 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6991 {
6992   checkConnectivityFullyDefined();
6993   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6994   renumberCells(ret->getConstPointer(),false);
6995   return ret.retn();
6996 }
6997
6998 /*!
6999  * This methods checks that cells are sorted by their types.
7000  * This method makes asumption (no check) that connectivity is correctly set before calling.
7001  */
7002 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7003 {
7004   checkFullyDefined();
7005   const int *conn=_nodal_connec->getConstPointer();
7006   const int *connI=_nodal_connec_index->getConstPointer();
7007   int nbOfCells=getNumberOfCells();
7008   std::set<INTERP_KERNEL::NormalizedCellType> types;
7009   for(const int *i=connI;i!=connI+nbOfCells;)
7010     {
7011       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7012       if(types.find(curType)!=types.end())
7013         return false;
7014       types.insert(curType);
7015       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7016     }
7017   return true;
7018 }
7019
7020 /*!
7021  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7022  * The geometric type order is specified by MED file.
7023  * 
7024  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7025  */
7026 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7027 {
7028   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7029 }
7030
7031 /*!
7032  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7033  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7034  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7035  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7036  */
7037 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7038 {
7039   checkFullyDefined();
7040   const int *conn=_nodal_connec->getConstPointer();
7041   const int *connI=_nodal_connec_index->getConstPointer();
7042   int nbOfCells=getNumberOfCells();
7043   if(nbOfCells==0)
7044     return true;
7045   int lastPos=-1;
7046   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7047   for(const int *i=connI;i!=connI+nbOfCells;)
7048     {
7049       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7050       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7051       if(isTypeExists!=orderEnd)
7052         {
7053           int pos=(int)std::distance(orderBg,isTypeExists);
7054           if(pos<=lastPos)
7055             return false;
7056           lastPos=pos;
7057           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7058         }
7059       else
7060         {
7061           if(sg.find(curType)==sg.end())
7062             {
7063               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7064               sg.insert(curType);
7065             }
7066           else
7067             return false;
7068         }
7069     }
7070   return true;
7071 }
7072
7073 /*!
7074  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7075  * 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
7076  * 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'.
7077  */
7078 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7079 {
7080   checkConnectivityFullyDefined();
7081   int nbOfCells=getNumberOfCells();
7082   const int *conn=_nodal_connec->getConstPointer();
7083   const int *connI=_nodal_connec_index->getConstPointer();
7084   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7085   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7086   tmpa->alloc(nbOfCells,1);
7087   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7088   tmpb->fillWithZero();
7089   int *tmp=tmpa->getPointer();
7090   int *tmp2=tmpb->getPointer();
7091   for(const int *i=connI;i!=connI+nbOfCells;i++)
7092     {
7093       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7094       if(where!=orderEnd)
7095         {
7096           int pos=(int)std::distance(orderBg,where);
7097           tmp2[pos]++;
7098           tmp[std::distance(connI,i)]=pos;
7099         }
7100       else
7101         {
7102           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7103           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7104           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7105           throw INTERP_KERNEL::Exception(oss.str().c_str());
7106         }
7107     }
7108   nbPerType=tmpb.retn();
7109   return tmpa.retn();
7110 }
7111
7112 /*!
7113  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7114  *
7115  * \return a new object containing the old to new correspondance.
7116  *
7117  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7118  */
7119 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7120 {
7121   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7122 }
7123
7124 /*!
7125  * 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.
7126  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7127  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7128  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7129  */
7130 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7131 {
7132   DataArrayInt *nbPerType=0;
7133   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7134   nbPerType->decrRef();
7135   return tmpa->buildPermArrPerLevel();
7136 }
7137
7138 /*!
7139  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7140  * The number of cells remains unchanged after the call of this method.
7141  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7142  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7143  *
7144  * \return the array giving the correspondance old to new.
7145  */
7146 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7147 {
7148   checkFullyDefined();
7149   computeTypes();
7150   const int *conn=_nodal_connec->getConstPointer();
7151   const int *connI=_nodal_connec_index->getConstPointer();
7152   int nbOfCells=getNumberOfCells();
7153   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7154   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7155     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7156       {
7157         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7158         types.push_back(curType);
7159         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7160       }
7161   DataArrayInt *ret=DataArrayInt::New();
7162   ret->alloc(nbOfCells,1);
7163   int *retPtr=ret->getPointer();
7164   std::fill(retPtr,retPtr+nbOfCells,-1);
7165   int newCellId=0;
7166   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7167     {
7168       for(const int *i=connI;i!=connI+nbOfCells;i++)
7169         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7170           retPtr[std::distance(connI,i)]=newCellId++;
7171     }
7172   renumberCells(retPtr,false);
7173   return ret;
7174 }
7175
7176 /*!
7177  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7178  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7179  * This method makes asumption that connectivity is correctly set before calling.
7180  */
7181 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7182 {
7183   checkConnectivityFullyDefined();
7184   const int *conn=_nodal_connec->getConstPointer();
7185   const int *connI=_nodal_connec_index->getConstPointer();
7186   int nbOfCells=getNumberOfCells();
7187   std::vector<MEDCouplingUMesh *> ret;
7188   for(const int *i=connI;i!=connI+nbOfCells;)
7189     {
7190       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7191       int beginCellId=(int)std::distance(connI,i);
7192       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7193       int endCellId=(int)std::distance(connI,i);
7194       int sz=endCellId-beginCellId;
7195       int *cells=new int[sz];
7196       for(int j=0;j<sz;j++)
7197         cells[j]=beginCellId+j;
7198       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7199       delete [] cells;
7200       ret.push_back(m);
7201     }
7202   return ret;
7203 }
7204
7205 /*!
7206  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7207  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7208  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7209  *
7210  * \return a newly allocated instance, that the caller must manage.
7211  * \throw If \a this contains more than one geometric type.
7212  * \throw If the nodal connectivity of \a this is not fully defined.
7213  * \throw If the internal data is not coherent.
7214  */
7215 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7216 {
7217   checkConnectivityFullyDefined();
7218   if(_types.size()!=1)
7219     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7220   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7221   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7222   ret->setCoords(getCoords());
7223   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7224   if(retC)
7225     {
7226       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7227       retC->setNodalConnectivity(c);
7228     }
7229   else
7230     {
7231       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7232       if(!retD)
7233         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7234       DataArrayInt *c=0,*ci=0;
7235       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7236       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7237       retD->setNodalConnectivity(cs,cis);
7238     }
7239   return ret.retn();
7240 }
7241
7242 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7243 {
7244   checkConnectivityFullyDefined();
7245   if(_types.size()!=1)
7246     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7247   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7248   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7249   if(cm.isDynamic())
7250     {
7251       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7252       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7253       throw INTERP_KERNEL::Exception(oss.str().c_str());
7254     }
7255   int nbCells=getNumberOfCells();
7256   int typi=(int)typ;
7257   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7258   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7259   int *outPtr=connOut->getPointer();
7260   const int *conn=_nodal_connec->begin();
7261   const int *connI=_nodal_connec_index->begin();
7262   nbNodesPerCell++;
7263   for(int i=0;i<nbCells;i++,connI++)
7264     {
7265       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7266         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7267       else
7268         {
7269           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 << ") !";
7270           throw INTERP_KERNEL::Exception(oss.str().c_str());
7271         }
7272     }
7273   return connOut.retn();
7274 }
7275
7276 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7277 {
7278   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7279   checkConnectivityFullyDefined();
7280   if(_types.size()!=1)
7281     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7282   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7283   if(lgth<nbCells)
7284     throw INTERP_KERNEL::Exception(msg0);
7285   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7286   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7287   int *cp(c->getPointer()),*cip(ci->getPointer());
7288   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7289   cip[0]=0;
7290   for(int i=0;i<nbCells;i++,cip++,incip++)
7291     {
7292       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7293       int delta(stop-strt);
7294       if(delta>=1)
7295         {
7296           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7297             cp=std::copy(incp+strt,incp+stop,cp);
7298           else
7299             throw INTERP_KERNEL::Exception(msg0);
7300         }
7301       else
7302         throw INTERP_KERNEL::Exception(msg0);
7303       cip[1]=cip[0]+delta;
7304     }
7305   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7306 }
7307
7308 /*!
7309  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7310  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7311  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7312  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7313  * are not used here to avoid the build of big permutation array.
7314  *
7315  * \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
7316  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7317  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7318  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7319  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7320  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7321  * \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
7322  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7323  */
7324 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7325                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7326                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7327 {
7328   std::vector<const MEDCouplingUMesh *> ms2;
7329   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7330     if(*it)
7331       {
7332         (*it)->checkConnectivityFullyDefined();
7333         ms2.push_back(*it);
7334       }
7335   if(ms2.empty())
7336     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7337   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7338   int meshDim=ms2[0]->getMeshDimension();
7339   std::vector<const MEDCouplingUMesh *> m1ssm;
7340   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7341   //
7342   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7343   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7344   int fake=0,rk=0;
7345   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7346   ret1->alloc(0,1); ret2->alloc(0,1);
7347   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7348     {
7349       if(meshDim!=(*it)->getMeshDimension())
7350         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7351       if(refCoo!=(*it)->getCoords())
7352         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7353       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7354       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7355       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7356       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7357         {
7358           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7359           m1ssmSingleAuto.push_back(singleCell);
7360           m1ssmSingle.push_back(singleCell);
7361           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7362         }
7363     }
7364   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7365   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7366   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7367   for(std::size_t i=0;i<m1ssm.size();i++)
7368     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7369   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7370   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7371   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7372   return ret0.retn();
7373 }
7374
7375 /*!
7376  * This method returns a newly created DataArrayInt instance.
7377  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7378  */
7379 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7380 {
7381   checkFullyDefined();
7382   const int *conn=_nodal_connec->getConstPointer();
7383   const int *connIndex=_nodal_connec_index->getConstPointer();
7384   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7385   for(const int *w=begin;w!=end;w++)
7386     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7387       ret->pushBackSilent(*w);
7388   return ret.retn();
7389 }
7390
7391 /*!
7392  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7393  * are in [0:getNumberOfCells())
7394  */
7395 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7396 {
7397   checkFullyDefined();
7398   const int *conn=_nodal_connec->getConstPointer();
7399   const int *connI=_nodal_connec_index->getConstPointer();
7400   int nbOfCells=getNumberOfCells();
7401   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7402   int *tmp=new int[nbOfCells];
7403   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7404     {
7405       int j=0;
7406       for(const int *i=connI;i!=connI+nbOfCells;i++)
7407         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7408           tmp[std::distance(connI,i)]=j++;
7409     }
7410   DataArrayInt *ret=DataArrayInt::New();
7411   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7412   ret->copyStringInfoFrom(*da);
7413   int *retPtr=ret->getPointer();
7414   const int *daPtr=da->getConstPointer();
7415   int nbOfElems=da->getNbOfElems();
7416   for(int k=0;k<nbOfElems;k++)
7417     retPtr[k]=tmp[daPtr[k]];
7418   delete [] tmp;
7419   return ret;
7420 }
7421
7422 /*!
7423  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7424  * This method \b works \b for mesh sorted by type.
7425  * cells whose ids is in 'idsPerGeoType' array.
7426  * This method conserves coords and name of mesh.
7427  */
7428 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7429 {
7430   std::vector<int> code=getDistributionOfTypes();
7431   std::size_t nOfTypesInThis=code.size()/3;
7432   int sz=0,szOfType=0;
7433   for(std::size_t i=0;i<nOfTypesInThis;i++)
7434     {
7435       if(code[3*i]!=type)
7436         sz+=code[3*i+1];
7437       else
7438         szOfType=code[3*i+1];
7439     }
7440   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7441     if(*work<0 || *work>=szOfType)
7442       {
7443         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7444         oss << ". It should be in [0," << szOfType << ") !";
7445         throw INTERP_KERNEL::Exception(oss.str().c_str());
7446       }
7447   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7448   int *idsPtr=idsTokeep->getPointer();
7449   int offset=0;
7450   for(std::size_t i=0;i<nOfTypesInThis;i++)
7451     {
7452       if(code[3*i]!=type)
7453         for(int j=0;j<code[3*i+1];j++)
7454           *idsPtr++=offset+j;
7455       else
7456         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7457       offset+=code[3*i+1];
7458     }
7459   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7460   ret->copyTinyInfoFrom(this);
7461   return ret.retn();
7462 }
7463
7464 /*!
7465  * This method returns a vector of size 'this->getNumberOfCells()'.
7466  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7467  */
7468 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7469 {
7470   int ncell=getNumberOfCells();
7471   std::vector<bool> ret(ncell);
7472   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7473   const int *c=getNodalConnectivity()->getConstPointer();
7474   for(int i=0;i<ncell;i++)
7475     {
7476       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7477       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7478       ret[i]=cm.isQuadratic();
7479     }
7480   return ret;
7481 }
7482
7483 /*!
7484  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7485  */
7486 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7487 {
7488   if(other->getType()!=UNSTRUCTURED)
7489     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7490   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7491   return MergeUMeshes(this,otherC);
7492 }
7493
7494 /*!
7495  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7496  * computed by averaging coordinates of cell nodes, so this method is not a right
7497  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7498  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7499  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7500  *          components. The caller is to delete this array using decrRef() as it is
7501  *          no more needed.
7502  *  \throw If the coordinates array is not set.
7503  *  \throw If the nodal connectivity of cells is not defined.
7504  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7505  */
7506 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7507 {
7508   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7509   int spaceDim=getSpaceDimension();
7510   int nbOfCells=getNumberOfCells();
7511   ret->alloc(nbOfCells,spaceDim);
7512   ret->copyStringInfoFrom(*getCoords());
7513   double *ptToFill=ret->getPointer();
7514   const int *nodal=_nodal_connec->getConstPointer();
7515   const int *nodalI=_nodal_connec_index->getConstPointer();
7516   const double *coor=_coords->getConstPointer();
7517   for(int i=0;i<nbOfCells;i++)
7518     {
7519       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7520       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7521       ptToFill+=spaceDim;
7522     }
7523   return ret.retn();
7524 }
7525
7526 /*!
7527  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7528  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7529  * 
7530  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7531  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7532  * 
7533  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7534  * \throw If \a this is not fully defined (coordinates and connectivity)
7535  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7536  */
7537 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7538 {
7539   checkFullyDefined();
7540   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7541   int spaceDim=getSpaceDimension();
7542   int nbOfCells=getNumberOfCells();
7543   int nbOfNodes=getNumberOfNodes();
7544   ret->alloc(nbOfCells,spaceDim);
7545   double *ptToFill=ret->getPointer();
7546   const int *nodal=_nodal_connec->getConstPointer();
7547   const int *nodalI=_nodal_connec_index->getConstPointer();
7548   const double *coor=_coords->getConstPointer();
7549   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7550     {
7551       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7552       std::fill(ptToFill,ptToFill+spaceDim,0.);
7553       if(type!=INTERP_KERNEL::NORM_POLYHED)
7554         {
7555           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7556             {
7557               if(*conn>=0 && *conn<nbOfNodes)
7558                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7559               else
7560                 {
7561                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7562                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7563                 }
7564             }
7565           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7566           if(nbOfNodesInCell>0)
7567             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7568           else
7569             {
7570               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7571               throw INTERP_KERNEL::Exception(oss.str().c_str());
7572             }
7573         }
7574       else
7575         {
7576           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7577           s.erase(-1);
7578           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7579             {
7580               if(*it>=0 && *it<nbOfNodes)
7581                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7582               else
7583                 {
7584                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7585                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7586                 }
7587             }
7588           if(!s.empty())
7589             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7590           else
7591             {
7592               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7593               throw INTERP_KERNEL::Exception(oss.str().c_str());
7594             }
7595         }
7596     }
7597   return ret.retn();
7598 }
7599
7600 /*!
7601  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7602  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7603  * are specified via an array of cell ids. 
7604  *  \warning Validity of the specified cell ids is not checked! 
7605  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7606  *  \param [in] begin - an array of cell ids of interest.
7607  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7608  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7609  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7610  *          caller is to delete this array using decrRef() as it is no more needed. 
7611  *  \throw If the coordinates array is not set.
7612  *  \throw If the nodal connectivity of cells is not defined.
7613  *
7614  *  \if ENABLE_EXAMPLES
7615  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7616  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7617  *  \endif
7618  */
7619 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7620 {
7621   DataArrayDouble *ret=DataArrayDouble::New();
7622   int spaceDim=getSpaceDimension();
7623   int nbOfTuple=(int)std::distance(begin,end);
7624   ret->alloc(nbOfTuple,spaceDim);
7625   double *ptToFill=ret->getPointer();
7626   double *tmp=new double[spaceDim];
7627   const int *nodal=_nodal_connec->getConstPointer();
7628   const int *nodalI=_nodal_connec_index->getConstPointer();
7629   const double *coor=_coords->getConstPointer();
7630   for(const int *w=begin;w!=end;w++)
7631     {
7632       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7633       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7634       ptToFill+=spaceDim;
7635     }
7636   delete [] tmp;
7637   return ret;
7638 }
7639
7640 /*!
7641  * 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".
7642  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7643  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7644  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7645  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7646  * 
7647  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7648  * \throw If spaceDim!=3 or meshDim!=2.
7649  * \throw If connectivity of \a this is invalid.
7650  * \throw If connectivity of a cell in \a this points to an invalid node.
7651  */
7652 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7653 {
7654   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7655   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7656   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7657     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7658   ret->alloc(nbOfCells,4);
7659   double *retPtr(ret->getPointer());
7660   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7661   const double *coor(_coords->begin());
7662   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7663     {
7664       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7665       if(nodalI[1]-nodalI[0]>=3)
7666         {
7667           for(int j=0;j<3;j++)
7668             {
7669               int nodeId(nodal[nodalI[0]+1+j]);
7670               if(nodeId>=0 && nodeId<nbOfNodes)
7671                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7672               else
7673                 {
7674                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7675                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7676                 }
7677             }
7678         }
7679       else
7680         {
7681           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7682           throw INTERP_KERNEL::Exception(oss.str().c_str());
7683         }
7684       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7685       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7686     }
7687   return ret.retn();
7688 }
7689
7690 /*!
7691  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7692  * 
7693  */
7694 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7695 {
7696   if(!da)
7697     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7698   da->checkAllocated();
7699   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7700   ret->setCoords(da);
7701   int nbOfTuples=da->getNumberOfTuples();
7702   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7703   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7704   c->alloc(2*nbOfTuples,1);
7705   cI->alloc(nbOfTuples+1,1);
7706   int *cp=c->getPointer();
7707   int *cip=cI->getPointer();
7708   *cip++=0;
7709   for(int i=0;i<nbOfTuples;i++)
7710     {
7711       *cp++=INTERP_KERNEL::NORM_POINT1;
7712       *cp++=i;
7713       *cip++=2*(i+1);
7714     }
7715   ret->setConnectivity(c,cI,true);
7716   return ret.retn();
7717 }
7718 /*!
7719  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7720  * Cells and nodes of
7721  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7722  *  \param [in] mesh1 - the first mesh.
7723  *  \param [in] mesh2 - the second mesh.
7724  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7725  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7726  *          is no more needed.
7727  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7728  *  \throw If the coordinates array is not set in none of the meshes.
7729  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7730  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7731  */
7732 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7733 {
7734   std::vector<const MEDCouplingUMesh *> tmp(2);
7735   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7736   return MergeUMeshes(tmp);
7737 }
7738
7739 /*!
7740  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7741  * Cells and nodes of
7742  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7743  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7744  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7745  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7746  *          is no more needed.
7747  *  \throw If \a a.size() == 0.
7748  *  \throw If \a a[ *i* ] == NULL.
7749  *  \throw If the coordinates array is not set in none of the meshes.
7750  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7751  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7752  */
7753 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7754 {
7755   std::size_t sz=a.size();
7756   if(sz==0)
7757     return MergeUMeshesLL(a);
7758   for(std::size_t ii=0;ii<sz;ii++)
7759     if(!a[ii])
7760       {
7761         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7762         throw INTERP_KERNEL::Exception(oss.str().c_str());
7763       }
7764   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7765   std::vector< const MEDCouplingUMesh * > aa(sz);
7766   int spaceDim=-3;
7767   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7768     {
7769       const MEDCouplingUMesh *cur=a[i];
7770       const DataArrayDouble *coo=cur->getCoords();
7771       if(coo)
7772         spaceDim=coo->getNumberOfComponents();
7773     }
7774   if(spaceDim==-3)
7775     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7776   for(std::size_t i=0;i<sz;i++)
7777     {
7778       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7779       aa[i]=bb[i];
7780     }
7781   return MergeUMeshesLL(aa);
7782 }
7783
7784 /// @cond INTERNAL
7785
7786 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7787 {
7788   if(a.empty())
7789     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7790   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7791   int meshDim=(*it)->getMeshDimension();
7792   int nbOfCells=(*it)->getNumberOfCells();
7793   int meshLgth=(*it++)->getMeshLength();
7794   for(;it!=a.end();it++)
7795     {
7796       if(meshDim!=(*it)->getMeshDimension())
7797         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7798       nbOfCells+=(*it)->getNumberOfCells();
7799       meshLgth+=(*it)->getMeshLength();
7800     }
7801   std::vector<const MEDCouplingPointSet *> aps(a.size());
7802   std::copy(a.begin(),a.end(),aps.begin());
7803   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7804   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7805   ret->setCoords(pts);
7806   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7807   c->alloc(meshLgth,1);
7808   int *cPtr=c->getPointer();
7809   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7810   cI->alloc(nbOfCells+1,1);
7811   int *cIPtr=cI->getPointer();
7812   *cIPtr++=0;
7813   int offset=0;
7814   int offset2=0;
7815   for(it=a.begin();it!=a.end();it++)
7816     {
7817       int curNbOfCell=(*it)->getNumberOfCells();
7818       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7819       const int *curC=(*it)->_nodal_connec->getConstPointer();
7820       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7821       for(int j=0;j<curNbOfCell;j++)
7822         {
7823           const int *src=curC+curCI[j];
7824           *cPtr++=*src++;
7825           for(;src!=curC+curCI[j+1];src++,cPtr++)
7826             {
7827               if(*src!=-1)
7828                 *cPtr=*src+offset2;
7829               else
7830                 *cPtr=-1;
7831             }
7832         }
7833       offset+=curCI[curNbOfCell];
7834       offset2+=(*it)->getNumberOfNodes();
7835     }
7836   //
7837   ret->setConnectivity(c,cI,true);
7838   return ret.retn();
7839 }
7840
7841 /// @endcond
7842
7843 /*!
7844  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7845  * dimension and sharing the node coordinates array.
7846  * All cells of the first mesh precede all cells of the second mesh
7847  * within the result mesh. 
7848  *  \param [in] mesh1 - the first mesh.
7849  *  \param [in] mesh2 - the second mesh.
7850  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7851  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7852  *          is no more needed.
7853  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7854  *  \throw If the meshes do not share the node coordinates array.
7855  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7856  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7857  */
7858 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7859 {
7860   std::vector<const MEDCouplingUMesh *> tmp(2);
7861   tmp[0]=mesh1; tmp[1]=mesh2;
7862   return MergeUMeshesOnSameCoords(tmp);
7863 }
7864
7865 /*!
7866  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7867  * dimension and sharing the node coordinates array.
7868  * All cells of the *i*-th mesh precede all cells of the
7869  * (*i*+1)-th mesh within the result mesh.
7870  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7871  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7872  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7873  *          is no more needed.
7874  *  \throw If \a a.size() == 0.
7875  *  \throw If \a a[ *i* ] == NULL.
7876  *  \throw If the meshes do not share the node coordinates array.
7877  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7878  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7879  */
7880 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7881 {
7882   if(meshes.empty())
7883     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7884   for(std::size_t ii=0;ii<meshes.size();ii++)
7885     if(!meshes[ii])
7886       {
7887         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7888         throw INTERP_KERNEL::Exception(oss.str().c_str());
7889       }
7890   const DataArrayDouble *coords=meshes.front()->getCoords();
7891   int meshDim=meshes.front()->getMeshDimension();
7892   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7893   int meshLgth=0;
7894   int meshIndexLgth=0;
7895   for(;iter!=meshes.end();iter++)
7896     {
7897       if(coords!=(*iter)->getCoords())
7898         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7899       if(meshDim!=(*iter)->getMeshDimension())
7900         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7901       meshLgth+=(*iter)->getMeshLength();
7902       meshIndexLgth+=(*iter)->getNumberOfCells();
7903     }
7904   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7905   nodal->alloc(meshLgth,1);
7906   int *nodalPtr=nodal->getPointer();
7907   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7908   nodalIndex->alloc(meshIndexLgth+1,1);
7909   int *nodalIndexPtr=nodalIndex->getPointer();
7910   int offset=0;
7911   for(iter=meshes.begin();iter!=meshes.end();iter++)
7912     {
7913       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7914       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7915       int nbOfCells=(*iter)->getNumberOfCells();
7916       int meshLgth2=(*iter)->getMeshLength();
7917       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7918       if(iter!=meshes.begin())
7919         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7920       else
7921         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7922       offset+=meshLgth2;
7923     }
7924   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7925   ret->setName("merge");
7926   ret->setMeshDimension(meshDim);
7927   ret->setConnectivity(nodal,nodalIndex,true);
7928   ret->setCoords(coords);
7929   return ret;
7930 }
7931
7932 /*!
7933  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7934  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7935  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7936  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7937  * New" mode are returned for each input mesh.
7938  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7939  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7940  *          valid values [0,1,2], see zipConnectivityTraducer().
7941  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7942  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7943  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7944  *          no more needed.
7945  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7946  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7947  *          is no more needed.
7948  *  \throw If \a meshes.size() == 0.
7949  *  \throw If \a meshes[ *i* ] == NULL.
7950  *  \throw If the meshes do not share the node coordinates array.
7951  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7952  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7953  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7954  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7955  */
7956 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7957 {
7958   //All checks are delegated to MergeUMeshesOnSameCoords
7959   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7961   corr.resize(meshes.size());
7962   std::size_t nbOfMeshes=meshes.size();
7963   int offset=0;
7964   const int *o2nPtr=o2n->getConstPointer();
7965   for(std::size_t i=0;i<nbOfMeshes;i++)
7966     {
7967       DataArrayInt *tmp=DataArrayInt::New();
7968       int curNbOfCells=meshes[i]->getNumberOfCells();
7969       tmp->alloc(curNbOfCells,1);
7970       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7971       offset+=curNbOfCells;
7972       tmp->setName(meshes[i]->getName());
7973       corr[i]=tmp;
7974     }
7975   return ret.retn();
7976 }
7977
7978 /*!
7979  * Makes all given meshes share the nodal connectivity array. The common connectivity
7980  * array is created by concatenating the connectivity arrays of all given meshes. All
7981  * the given meshes must be of the same space dimension but dimension of cells **can
7982  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7983  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7984  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7985  *  \param [in,out] meshes - a vector of meshes to update.
7986  *  \throw If any of \a meshes is NULL.
7987  *  \throw If the coordinates array is not set in any of \a meshes.
7988  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7989  *  \throw If \a meshes are of different space dimension.
7990  */
7991 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7992 {
7993   std::size_t sz=meshes.size();
7994   if(sz==0 || sz==1)
7995     return;
7996   std::vector< const DataArrayDouble * > coords(meshes.size());
7997   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7998   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7999     {
8000       if((*it))
8001         {
8002           (*it)->checkConnectivityFullyDefined();
8003           const DataArrayDouble *coo=(*it)->getCoords();
8004           if(coo)
8005             *it2=coo;
8006           else
8007             {
8008               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8009               oss << " has no coordinate array defined !";
8010               throw INTERP_KERNEL::Exception(oss.str().c_str());
8011             }
8012         }
8013       else
8014         {
8015           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8016           oss << " is null !";
8017           throw INTERP_KERNEL::Exception(oss.str().c_str());
8018         }
8019     }
8020   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8021   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8022   int offset=(*it)->getNumberOfNodes();
8023   (*it++)->setCoords(res);
8024   for(;it!=meshes.end();it++)
8025     {
8026       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8027       (*it)->setCoords(res);
8028       (*it)->shiftNodeNumbersInConn(offset);
8029       offset+=oldNumberOfNodes;
8030     }
8031 }
8032
8033 /*!
8034  * Merges nodes coincident with a given precision within all given meshes that share
8035  * the nodal connectivity array. The given meshes **can be of different** mesh
8036  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8037  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8038  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8039  *  \param [in,out] meshes - a vector of meshes to update.
8040  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8041  *  \throw If any of \a meshes is NULL.
8042  *  \throw If the \a meshes do not share the same node coordinates array.
8043  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8044  */
8045 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8046 {
8047   if(meshes.empty())
8048     return ;
8049   std::set<const DataArrayDouble *> s;
8050   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8051     {
8052       if(*it)
8053         s.insert((*it)->getCoords());
8054       else
8055         {
8056           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 !";
8057           throw INTERP_KERNEL::Exception(oss.str().c_str());
8058         }
8059     }
8060   if(s.size()!=1)
8061     {
8062       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 !";
8063       throw INTERP_KERNEL::Exception(oss.str().c_str());
8064     }
8065   const DataArrayDouble *coo=*(s.begin());
8066   if(!coo)
8067     return;
8068   //
8069   DataArrayInt *comm,*commI;
8070   coo->findCommonTuples(eps,-1,comm,commI);
8071   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8072   int oldNbOfNodes=coo->getNumberOfTuples();
8073   int newNbOfNodes;
8074   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8075   if(oldNbOfNodes==newNbOfNodes)
8076     return ;
8077   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8078   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8079     {
8080       (*it)->renumberNodesInConn(o2n->getConstPointer());
8081       (*it)->setCoords(newCoords);
8082     } 
8083 }
8084
8085 /*!
8086  * 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.
8087  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8088  * \param isQuad specifies the policy of connectivity.
8089  * @ret in/out parameter in which the result will be append
8090  */
8091 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8092 {
8093   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8094   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8095   ret.push_back(cm.getExtrudedType());
8096   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8097   switch(flatType)
8098   {
8099     case INTERP_KERNEL::NORM_POINT1:
8100       {
8101         ret.push_back(connBg[1]);
8102         ret.push_back(connBg[1]+nbOfNodesPerLev);
8103         break;
8104       }
8105     case INTERP_KERNEL::NORM_SEG2:
8106       {
8107         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8108         ret.insert(ret.end(),conn,conn+4);
8109         break;
8110       }
8111     case INTERP_KERNEL::NORM_SEG3:
8112       {
8113         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8114         ret.insert(ret.end(),conn,conn+8);
8115         break;
8116       }
8117     case INTERP_KERNEL::NORM_QUAD4:
8118       {
8119         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8120         ret.insert(ret.end(),conn,conn+8);
8121         break;
8122       }
8123     case INTERP_KERNEL::NORM_TRI3:
8124       {
8125         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8126         ret.insert(ret.end(),conn,conn+6);
8127         break;
8128       }
8129     case INTERP_KERNEL::NORM_TRI6:
8130       {
8131         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,
8132           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8133         ret.insert(ret.end(),conn,conn+15);
8134         break;
8135       }
8136     case INTERP_KERNEL::NORM_QUAD8:
8137       {
8138         int conn[20]={
8139           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8140           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8141           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8142         };
8143         ret.insert(ret.end(),conn,conn+20);
8144         break;
8145       }
8146     case INTERP_KERNEL::NORM_POLYGON:
8147       {
8148         std::back_insert_iterator< std::vector<int> > ii(ret);
8149         std::copy(connBg+1,connEnd,ii);
8150         *ii++=-1;
8151         std::reverse_iterator<const int *> rConnBg(connEnd);
8152         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8153         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8154         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8155         for(std::size_t i=0;i<nbOfRadFaces;i++)
8156           {
8157             *ii++=-1;
8158             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8159             std::copy(conn,conn+4,ii);
8160           }
8161         break;
8162       }
8163     default:
8164       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8165   }
8166 }
8167
8168 /*!
8169  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8170  */
8171 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8172 {
8173   std::size_t i, ip1;
8174   double v[3]={0.,0.,0.};
8175   std::size_t sz=std::distance(begin,end);
8176   if(isQuadratic)
8177     sz/=2;
8178   for(i=0;i<sz;i++)
8179     {
8180       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];
8181       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8182       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8183     }
8184   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8185
8186   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8187   // SEG3 forming a circle):
8188   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8189     {
8190       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8191       for(std::size_t j=0;j<sz;j++)
8192         {
8193           if (j%2)  // current point i is quadratic, next point i+1 is standard
8194             {
8195               i = sz+j;
8196               ip1 = (j+1)%sz; // ip1 = "i+1"
8197             }
8198           else      // current point i is standard, next point i+1 is quadratic
8199             {
8200               i = j;
8201               ip1 = j+sz;
8202             }
8203           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8204           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8205           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8206         }
8207       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8208     }
8209   return (ret>0.);
8210 }
8211
8212 /*!
8213  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8214  */
8215 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8216 {
8217   std::vector<std::pair<int,int> > edges;
8218   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8219   const int *bgFace=begin;
8220   for(std::size_t i=0;i<nbOfFaces;i++)
8221     {
8222       const int *endFace=std::find(bgFace+1,end,-1);
8223       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8224       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8225         {
8226           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8227           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8228             return false;
8229           edges.push_back(p1);
8230         }
8231       bgFace=endFace+1;
8232     }
8233   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8234 }
8235
8236 /*!
8237  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8238  */
8239 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8240 {
8241   double vec0[3],vec1[3];
8242   std::size_t sz=std::distance(begin,end);
8243   if(sz%2!=0)
8244     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8245   int nbOfNodes=(int)sz/2;
8246   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8247   const double *pt0=coords+3*begin[0];
8248   const double *pt1=coords+3*begin[nbOfNodes];
8249   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8250   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8251 }
8252
8253 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8254 {
8255   std::size_t sz=std::distance(begin,end);
8256   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8257   std::size_t nbOfNodes(sz/2);
8258   std::copy(begin,end,(int *)tmp);
8259   for(std::size_t j=1;j<nbOfNodes;j++)
8260     {
8261       begin[j]=tmp[nbOfNodes-j];
8262       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8263     }
8264 }
8265
8266 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8267 {
8268   std::size_t sz=std::distance(begin,end);
8269   if(sz!=4)
8270     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8271   double vec0[3],vec1[3];
8272   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8273   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]; 
8274   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;
8275 }
8276
8277 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8278 {
8279   std::size_t sz=std::distance(begin,end);
8280   if(sz!=5)
8281     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8282   double vec0[3];
8283   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8284   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8285   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8286 }
8287
8288 /*!
8289  * 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 ) 
8290  * 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
8291  * a 2D space.
8292  *
8293  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8294  * \param [in] coords the coordinates with nb of components exactly equal to 3
8295  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8296  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8297  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8298  */
8299 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8300 {
8301   int nbFaces=std::count(begin+1,end,-1)+1;
8302   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8303   double *vPtr=v->getPointer();
8304   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8305   double *pPtr=p->getPointer();
8306   const int *stFaceConn=begin+1;
8307   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8308     {
8309       const int *endFaceConn=std::find(stFaceConn,end,-1);
8310       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8311       stFaceConn=endFaceConn+1;
8312     }
8313   pPtr=p->getPointer(); vPtr=v->getPointer();
8314   DataArrayInt *comm1=0,*commI1=0;
8315   v->findCommonTuples(eps,-1,comm1,commI1);
8316   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8317   const int *comm1Ptr=comm1->getConstPointer();
8318   const int *commI1Ptr=commI1->getConstPointer();
8319   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8320   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8321   //
8322   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8323   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8324   mm->finishInsertingCells();
8325   //
8326   for(int i=0;i<nbOfGrps1;i++)
8327     {
8328       int vecId=comm1Ptr[commI1Ptr[i]];
8329       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8330       DataArrayInt *comm2=0,*commI2=0;
8331       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8332       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8333       const int *comm2Ptr=comm2->getConstPointer();
8334       const int *commI2Ptr=commI2->getConstPointer();
8335       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8336       for(int j=0;j<nbOfGrps2;j++)
8337         {
8338           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8339             {
8340               res->insertAtTheEnd(begin,end);
8341               res->pushBackSilent(-1);
8342             }
8343           else
8344             {
8345               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8346               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8347               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8348               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8349               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8350               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8351               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8352               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8353               const int *idsNodePtr=idsNode->getConstPointer();
8354               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];
8355               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8356               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8357               if(std::abs(norm)>eps)
8358                 {
8359                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8360                   mm3->rotate(center,vec,angle);
8361                 }
8362               mm3->changeSpaceDimension(2);
8363               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8364               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8365               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8366               int nbOfCells=mm4->getNumberOfCells();
8367               for(int k=0;k<nbOfCells;k++)
8368                 {
8369                   int l=0;
8370                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8371                     res->pushBackSilent(idsNodePtr[*work]);
8372                   res->pushBackSilent(-1);
8373                 }
8374             }
8375         }
8376     }
8377   res->popBackSilent();
8378 }
8379
8380 /*!
8381  * 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
8382  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8383  * 
8384  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8385  * \param [in] coords coordinates expected to have 3 components.
8386  * \param [in] begin start of the nodal connectivity of the face.
8387  * \param [in] end end of the nodal connectivity (excluded) of the face.
8388  * \param [out] v the normalized vector of size 3
8389  * \param [out] p the pos of plane
8390  */
8391 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8392 {
8393   std::size_t nbPoints=std::distance(begin,end);
8394   if(nbPoints<3)
8395     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8396   double vec[3]={0.,0.,0.};
8397   std::size_t j=0;
8398   bool refFound=false;
8399   for(;j<nbPoints-1 && !refFound;j++)
8400     {
8401       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8402       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8403       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8404       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8405       if(norm>eps)
8406         {
8407           refFound=true;
8408           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8409         }
8410     }
8411   for(std::size_t i=j;i<nbPoints-1;i++)
8412     {
8413       double curVec[3];
8414       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8415       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8416       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8417       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8418       if(norm<eps)
8419         continue;
8420       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8421       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];
8422       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8423       if(norm>eps)
8424         {
8425           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8426           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8427           return ;
8428         }
8429     }
8430   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8431 }
8432
8433 /*!
8434  * This method tries to obtain a well oriented polyhedron.
8435  * If the algorithm fails, an exception will be thrown.
8436  */
8437 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8438 {
8439   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8440   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8441   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8442   isPerm[0]=true;
8443   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8444   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8445   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8446   //
8447   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8448     {
8449       bgFace=begin;
8450       std::size_t smthChanged=0;
8451       for(std::size_t i=0;i<nbOfFaces;i++)
8452         {
8453           endFace=std::find(bgFace+1,end,-1);
8454           nbOfEdgesInFace=std::distance(bgFace,endFace);
8455           if(!isPerm[i])
8456             {
8457               bool b;
8458               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8459                 {
8460                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8461                   std::pair<int,int> p2(p1.second,p1.first);
8462                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8463                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8464                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8465                 }
8466               if(isPerm[i])
8467                 { 
8468                   if(!b)
8469                     std::reverse(bgFace+1,endFace);
8470                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8471                     {
8472                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8473                       std::pair<int,int> p2(p1.second,p1.first);
8474                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8475                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8476                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8477                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8478                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8479                       if(it!=edgesOK.end())
8480                         {
8481                           edgesOK.erase(it);
8482                           edgesFinished.push_back(p1);
8483                         }
8484                       else
8485                         edgesOK.push_back(p1);
8486                     }
8487                 }
8488             }
8489           bgFace=endFace+1;
8490         }
8491       if(smthChanged==0)
8492         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8493     }
8494   if(!edgesOK.empty())
8495     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8496   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8497     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8498       bgFace=begin;
8499       for(std::size_t i=0;i<nbOfFaces;i++)
8500         {
8501           endFace=std::find(bgFace+1,end,-1);
8502           std::reverse(bgFace+1,endFace);
8503           bgFace=endFace+1;
8504         }
8505     }
8506 }
8507
8508 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8509 {
8510   int nbOfNodesExpected(skin->getNumberOfNodes());
8511   const int *n2oPtr(n2o->getConstPointer());
8512   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8513   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8514   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8515   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8516   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8517   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8518   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8519   if(nbOfNodesExpected<1)
8520     return ret.retn();
8521   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8522   *work++=n2oPtr[prevNode];
8523   for(int i=1;i<nbOfNodesExpected;i++)
8524     {
8525       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8526         {
8527           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8528           conn.erase(prevNode);
8529           if(conn.size()==1)
8530             {
8531               int curNode(*(conn.begin()));
8532               *work++=n2oPtr[curNode];
8533               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8534               shar.erase(prevCell);
8535               if(shar.size()==1)
8536                 {
8537                   prevCell=*(shar.begin());
8538                   prevNode=curNode;
8539                 }
8540               else
8541                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8542             }
8543           else
8544             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8545         }
8546       else
8547         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8548     }
8549   return ret.retn();
8550 }
8551
8552 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8553 {
8554   int nbOfNodesExpected(skin->getNumberOfNodes());
8555   int nbOfTurn(nbOfNodesExpected/2);
8556   const int *n2oPtr(n2o->getConstPointer());
8557   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8558   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8559   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8560   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8561   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8562   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8563   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8564   if(nbOfNodesExpected<1)
8565     return ret.retn();
8566   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8567   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8568   for(int i=1;i<nbOfTurn;i++)
8569     {
8570       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8571         {
8572           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8573           conn.erase(prevNode);
8574           if(conn.size()==1)
8575             {
8576               int curNode(*(conn.begin()));
8577               *work=n2oPtr[curNode];
8578               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8579               shar.erase(prevCell);
8580               if(shar.size()==1)
8581                 {
8582                   int curCell(*(shar.begin()));
8583                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8584                   prevCell=curCell;
8585                   prevNode=curNode;
8586                   work++;
8587                 }
8588               else
8589                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8590             }
8591           else
8592             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8593         }
8594       else
8595         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8596     }
8597   return ret.retn();
8598 }
8599
8600 /*!
8601  * This method makes the assumption spacedimension == meshdimension == 2.
8602  * This method works only for linear cells.
8603  * 
8604  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8605  */
8606 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8607 {
8608   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8609     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8610   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8611   int oldNbOfNodes(skin->getNumberOfNodes());
8612   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8613   int nbOfNodesExpected(skin->getNumberOfNodes());
8614   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8615   int nbCells(skin->getNumberOfCells());
8616   if(nbCells==nbOfNodesExpected)
8617     return buildUnionOf2DMeshLinear(skin,n2o);
8618   else if(2*nbCells==nbOfNodesExpected)
8619     return buildUnionOf2DMeshQuadratic(skin,n2o);
8620   else
8621     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8622 }
8623
8624 /*!
8625  * This method makes the assumption spacedimension == meshdimension == 3.
8626  * This method works only for linear cells.
8627  * 
8628  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8629  */
8630 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8631 {
8632   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8633     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8634   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8635   const int *conn=m->getNodalConnectivity()->getConstPointer();
8636   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8637   int nbOfCells=m->getNumberOfCells();
8638   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8639   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8640   if(nbOfCells<1)
8641     return ret.retn();
8642   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8643   for(int i=1;i<nbOfCells;i++)
8644     {
8645       *work++=-1;
8646       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8647     }
8648   return ret.retn();
8649 }
8650
8651 /*!
8652  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8653  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8654  */
8655 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8656 {
8657   double *w=zipFrmt;
8658   if(spaceDim==3)
8659     for(int i=0;i<nbOfNodesInCell;i++)
8660       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8661   else if(spaceDim==2)
8662     {
8663       for(int i=0;i<nbOfNodesInCell;i++)
8664         {
8665           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8666           *w++=0.;
8667         }
8668     }
8669   else
8670     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8671 }
8672
8673 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8674 {
8675   int nbOfCells=getNumberOfCells();
8676   if(nbOfCells<=0)
8677     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8678   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};
8679   ofs << "  <" << getVTKDataSetType() << ">\n";
8680   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8681   ofs << "      <PointData>\n" << pointData << std::endl;
8682   ofs << "      </PointData>\n";
8683   ofs << "      <CellData>\n" << cellData << std::endl;
8684   ofs << "      </CellData>\n";
8685   ofs << "      <Points>\n";
8686   if(getSpaceDimension()==3)
8687     _coords->writeVTK(ofs,8,"Points",byteData);
8688   else
8689     {
8690       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8691       coo->writeVTK(ofs,8,"Points",byteData);
8692     }
8693   ofs << "      </Points>\n";
8694   ofs << "      <Cells>\n";
8695   const int *cPtr=_nodal_connec->getConstPointer();
8696   const int *cIPtr=_nodal_connec_index->getConstPointer();
8697   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8698   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8699   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8700   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8701   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8702   int szFaceOffsets=0,szConn=0;
8703   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8704     {
8705       *w2=cPtr[cIPtr[i]];
8706       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8707         {
8708           *w1=-1;
8709           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8710           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8711         }
8712       else
8713         {
8714           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8715           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8716           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8717           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8718           w4=std::copy(c.begin(),c.end(),w4);
8719         }
8720     }
8721   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8722   types->writeVTK(ofs,8,"UInt8","types",byteData);
8723   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8724   if(szFaceOffsets!=0)
8725     {//presence of Polyhedra
8726       connectivity->reAlloc(szConn);
8727       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8728       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8729       w1=faces->getPointer();
8730       for(int i=0;i<nbOfCells;i++)
8731         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8732           {
8733             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8734             *w1++=nbFaces;
8735             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8736             for(int j=0;j<nbFaces;j++)
8737               {
8738                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8739                 *w1++=(int)std::distance(w6,w5);
8740                 w1=std::copy(w6,w5,w1);
8741                 w6=w5+1;
8742               }
8743           }
8744       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8745     }
8746   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8747   ofs << "      </Cells>\n";
8748   ofs << "    </Piece>\n";
8749   ofs << "  </" << getVTKDataSetType() << ">\n";
8750 }
8751
8752 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8753 {
8754   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8755   if(_mesh_dim==-2)
8756     { stream << " Not set !"; return ; }
8757   stream << " Mesh dimension : " << _mesh_dim << ".";
8758   if(_mesh_dim==-1)
8759     return ;
8760   if(!_coords)
8761     { stream << " No coordinates set !"; return ; }
8762   if(!_coords->isAllocated())
8763     { stream << " Coordinates set but not allocated !"; return ; }
8764   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8765   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8766   if(!_nodal_connec_index)
8767     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8768   if(!_nodal_connec_index->isAllocated())
8769     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8770   int lgth=_nodal_connec_index->getNumberOfTuples();
8771   int cpt=_nodal_connec_index->getNumberOfComponents();
8772   if(cpt!=1 || lgth<1)
8773     return ;
8774   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8775 }
8776
8777 std::string MEDCouplingUMesh::getVTKDataSetType() const
8778 {
8779   return std::string("UnstructuredGrid");
8780 }
8781
8782 std::string MEDCouplingUMesh::getVTKFileExtension() const
8783 {
8784   return std::string("vtu");
8785 }
8786
8787 /*!
8788  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8789  * returns a result mesh constituted by polygons.
8790  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8791  * all nodes from m2.
8792  * The meshes should be in 2D space. In
8793  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8794  * meshes.
8795  *  \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
8796  *                      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)
8797  *  \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
8798  *                      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)
8799  *  \param [in] eps - precision used to detect coincident mesh entities.
8800  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8801  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8802  *         this array using decrRef() as it is no more needed.
8803  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8804  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8805  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8806  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8807  *         it is no more needed.  
8808  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8809  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8810  *         is no more needed.  
8811  *  \throw If the coordinates array is not set in any of the meshes.
8812  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8813  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8814  *
8815  *  \sa conformize2D, mergeNodes
8816  */
8817 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8818                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8819 {
8820   if(!m1 || !m2)
8821     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8822   m1->checkFullyDefined();
8823   m2->checkFullyDefined();
8824   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8825     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8826
8827   // Step 1: compute all edge intersections (new nodes)
8828   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8829   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8830   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8831   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8832   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8833                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8834                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8835   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8836   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8837   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8838
8839   // Step 2: re-order newly created nodes according to the ordering found in m2
8840   std::vector< std::vector<int> > intersectEdge2;
8841   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8842   subDiv2.clear(); dd5=0; dd6=0;
8843
8844   // Step 3:
8845   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8846   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8847   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8848                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8849
8850   // Step 4: Prepare final result:
8851   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8852   addCooDa->alloc((int)(addCoo.size())/2,2);
8853   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8854   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8855   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8856   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8857   std::vector<const DataArrayDouble *> coordss(4);
8858   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8859   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8860   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8861   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8862   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8863   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8864   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8865   ret->setConnectivity(conn,connI,true);
8866   ret->setCoords(coo);
8867   cellNb1=c1.retn(); cellNb2=c2.retn();
8868   return ret.retn();
8869 }
8870
8871 /// @cond INTERNAL
8872
8873 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8874 {
8875   if(candidates.empty())
8876     return false;
8877   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8878     {
8879       const std::vector<int>& pool(intersectEdge1[*it]);
8880       int tmp[2]; tmp[0]=start; tmp[1]=stop;
8881       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8882         {
8883           retVal=*it+1;
8884           return true;
8885         }
8886       tmp[0]=stop; tmp[1]=start;
8887       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8888         {
8889           retVal=-*it-1;
8890           return true;
8891         }
8892     }
8893   return false;
8894 }
8895
8896 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,
8897                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8898 {
8899   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8900   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8901   int nCells(mesh1D->getNumberOfCells());
8902   if(nCells!=(int)intersectEdge2.size())
8903     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8904   const DataArrayDouble *coo2(mesh1D->getCoords());
8905   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8906   const double *coo2Ptr(coo2->begin());
8907   int offset1(coords1->getNumberOfTuples());
8908   int offset2(offset1+coo2->getNumberOfTuples());
8909   int offset3(offset2+addCoo.size()/2);
8910   std::vector<double> addCooQuad;
8911   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8912   int tmp[4],cicnt(0),kk(0);
8913   for(int i=0;i<nCells;i++)
8914     {
8915       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8916       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8917       const std::vector<int>& subEdges(intersectEdge2[i]);
8918       int nbSubEdge(subEdges.size()/2);
8919       for(int j=0;j<nbSubEdge;j++,kk++)
8920         {
8921           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));
8922           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8923           INTERP_KERNEL::Edge *e2Ptr(e2);
8924           std::map<int,int>::const_iterator itm;
8925           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8926             {
8927               tmp[0]=INTERP_KERNEL::NORM_SEG3;
8928               itm=mergedNodes.find(subEdges[2*j]);
8929               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8930               itm=mergedNodes.find(subEdges[2*j+1]);
8931               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8932               tmp[3]=offset3+(int)addCooQuad.size()/2;
8933               double tmp2[2];
8934               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8935               cicnt+=4;
8936               cOut->insertAtTheEnd(tmp,tmp+4);
8937               ciOut->pushBackSilent(cicnt);
8938             }
8939           else
8940             {
8941               tmp[0]=INTERP_KERNEL::NORM_SEG2;
8942               itm=mergedNodes.find(subEdges[2*j]);
8943               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8944               itm=mergedNodes.find(subEdges[2*j+1]);
8945               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8946               cicnt+=3;
8947               cOut->insertAtTheEnd(tmp,tmp+3);
8948               ciOut->pushBackSilent(cicnt);
8949             }
8950           int tmp00;
8951           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8952             {
8953               idsInRetColinear->pushBackSilent(kk);
8954               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8955             }
8956         }
8957       e->decrRef();
8958     }
8959   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8960   ret->setConnectivity(cOut,ciOut,true);
8961   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8962   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8963   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8964   std::vector<const DataArrayDouble *> coordss(4);
8965   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8966   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8967   ret->setCoords(arr);
8968   return ret.retn();
8969 }
8970
8971 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8972 {
8973   std::vector<int> allEdges;
8974   for(const int *it2(descBg);it2!=descEnd;it2++)
8975     {
8976       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
8977       if(*it2>0)
8978         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8979       else
8980         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8981     }
8982   std::size_t nb(allEdges.size());
8983   if(nb%2!=0)
8984     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
8985   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8986   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8987   ret->setCoords(coords);
8988   ret->allocateCells(1);
8989   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
8990   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8991     connOut[kk]=allEdges[2*kk];
8992   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
8993   return ret.retn();
8994 }
8995
8996 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8997 {
8998   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
8999   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9000   std::size_t ii(0);
9001   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9002   if(sz!=std::distance(descBg,descEnd))
9003     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9004   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9005   std::vector<int> allEdges,centers;
9006   const double *coordsPtr(coords->begin());
9007   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9008   int offset(coords->getNumberOfTuples());
9009   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9010     {
9011       INTERP_KERNEL::NormalizedCellType typeOfSon;
9012       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9013       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9014       if(*it2>0)
9015         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9016       else
9017         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9018       if(edge1.size()==2)
9019         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9020       else
9021         {//the current edge has been subsplit -> create corresponding centers.
9022           std::size_t nbOfCentersToAppend(edge1.size()/2);
9023           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9024           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9025           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9026           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9027             {
9028               double tmpp[2];
9029               const double *aa(coordsPtr+2*(*it3++));
9030               const double *bb(coordsPtr+2*(*it3++));
9031               ee->getMiddleOfPoints(aa,bb,tmpp);
9032               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9033               centers.push_back(offset+k);
9034             }
9035         }
9036     }
9037   std::size_t nb(allEdges.size());
9038   if(nb%2!=0)
9039     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9040   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9041   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9042   if(addCoo->empty())
9043     ret->setCoords(coords);
9044   else
9045     {
9046       addCoo->rearrange(2);
9047       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9048       ret->setCoords(addCoo);
9049     }
9050   ret->allocateCells(1);
9051   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9052   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9053     connOut[kk]=allEdges[2*kk];
9054   connOut.insert(connOut.end(),centers.begin(),centers.end());
9055   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9056   return ret.retn();
9057 }
9058
9059 /*!
9060  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9061  * of those edges.
9062  *
9063  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9064  */
9065 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9066 {
9067   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9068   if(!cm.isQuadratic())
9069     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9070   else
9071     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9072 }
9073
9074 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9075 {
9076   bool isQuad(false);
9077   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9078     {
9079       const INTERP_KERNEL::Edge *ee(*it);
9080       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9081         isQuad=true;
9082     }
9083   if(!isQuad)
9084     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9085   else
9086     {
9087       const double *coo(mesh2D->getCoords()->begin());
9088       std::size_t sz(conn.size());
9089       std::vector<double> addCoo;
9090       std::vector<int> conn2(conn);
9091       int offset(mesh2D->getNumberOfNodes());
9092       for(std::size_t i=0;i<sz;i++)
9093         {
9094           double tmp[2];
9095           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9096           addCoo.insert(addCoo.end(),tmp,tmp+2);
9097           conn2.push_back(offset+(int)i);
9098         }
9099       mesh2D->getCoords()->rearrange(1);
9100       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9101       mesh2D->getCoords()->rearrange(2);
9102       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9103     }
9104 }
9105
9106 /*!
9107  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9108  *
9109  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9110  * a set of edges defined in \a splitMesh1D.
9111  */
9112 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9113                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9114 {
9115   std::size_t nb(edge1Bis.size()/2);
9116   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9117   int iEnd(splitMesh1D->getNumberOfCells());
9118   if(iEnd==0)
9119     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9120   std::size_t ii,jj;
9121   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9122   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9123   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9124   //
9125   if(jj==nb)
9126     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9127       out0.resize(1); out1.resize(1);
9128       std::vector<int>& connOut(out0[0]);
9129       connOut.resize(nbOfEdgesOf2DCellSplit);
9130       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9131       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9132       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9133         {
9134           connOut[kk]=edge1Bis[2*kk];
9135           edgesPtr[kk]=edge1BisPtr[2*kk];
9136         }
9137     }
9138   else
9139     {
9140       // [i,iEnd[ contains the
9141       out0.resize(2); out1.resize(2);
9142       std::vector<int>& connOutLeft(out0[0]);
9143       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9144       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9145       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9146       for(std::size_t k=ii;k<jj+1;k++)
9147         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9148       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9149       for(int ik=0;ik<iEnd;ik++)
9150         {
9151           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9152           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9153           ees[ik]=ee;
9154         }
9155       for(int ik=iEnd-1;ik>=0;ik--)
9156         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9157       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9158         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9159       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9160       for(int ik=0;ik<iEnd;ik++)
9161         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9162       eright.insert(eright.end(),ees.begin(),ees.end());
9163     }
9164 }
9165
9166 /// @endcond
9167
9168 /// @cond INTERNAL
9169
9170 struct CellInfo
9171 {
9172 public:
9173   CellInfo() { }
9174   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9175 public:
9176   std::vector<int> _edges;
9177   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9178 };
9179
9180 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9181 {
9182   std::size_t nbe(edges.size());
9183   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9184   for(std::size_t i=0;i<nbe;i++)
9185     {
9186       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9187       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9188     }
9189   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9190   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9191   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9192 }
9193
9194 class EdgeInfo
9195 {
9196 public:
9197   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9198   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9199   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9200   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9201   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9202 private:
9203   int _istart;
9204   int _iend;
9205   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9206   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9207   int _left;
9208   int _right;
9209 };
9210
9211 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9212 {
9213   const MEDCouplingUMesh *mesh(_mesh);
9214   if(mesh)
9215     return ;
9216   if(_right<pos)
9217     return ;
9218   if(_left>pos)
9219     { _left++; _right++; return ; }
9220   if(_right==pos)
9221     {
9222       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9223       if((isLeft && isRight) || (!isLeft && !isRight))
9224         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9225       if(isLeft)
9226         return ;
9227       if(isRight)
9228         {
9229           _right++;
9230           return ;
9231         }
9232     }
9233   if(_left==pos)
9234     {
9235       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9236       if((isLeft && isRight) || (!isLeft && !isRight))
9237         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9238       if(isLeft)
9239         {
9240           _right++;
9241           return ;
9242         }
9243       if(isRight)
9244         {
9245           _left++;
9246           _right++;
9247           return ;
9248         }
9249     }
9250 }
9251
9252 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9253 {
9254   const MEDCouplingUMesh *mesh(_mesh);
9255   if(!mesh)
9256     {
9257       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9258     }
9259   else
9260     {// not fully splitting cell case
9261       if(mesh2D->getNumberOfCells()==1)
9262         {//little optimization. 1 cell no need to find in which cell mesh is !
9263           neighbors[0]=offset; neighbors[1]=offset;
9264           return;
9265         }
9266       else
9267         {
9268           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9269           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9270           if(cellId==-1)
9271             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9272           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9273         }
9274     }
9275 }
9276
9277 class VectorOfCellInfo
9278 {
9279 public:
9280   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9281   std::size_t size() const { return _pool.size(); }
9282   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9283   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);
9284   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9285   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9286   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9287   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9288 private:
9289   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9290   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9291   const CellInfo& get(int pos) const;
9292   CellInfo& get(int pos);
9293 private:
9294   std::vector<CellInfo> _pool;
9295   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9296   std::vector<EdgeInfo> _edge_info;
9297 };
9298
9299 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9300 {
9301   _pool[0]._edges=edges;
9302   _pool[0]._edges_ptr=edgesPtr;
9303 }
9304
9305 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9306 {
9307   if(_pool.empty())
9308     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9309   if(_pool.size()==1)
9310     return 0;
9311   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9312   if(!zeMesh)
9313     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9314   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9315   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9316 }
9317
9318 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)
9319 {
9320   get(pos);//to check pos
9321   bool isFast(pos==0 && _pool.size()==1);
9322   std::size_t sz(edges.size());
9323   // dealing with edges
9324   if(sz==1)
9325     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9326   else
9327     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9328   //
9329   std::vector<CellInfo> pool(_pool.size()-1+sz);
9330   for(int i=0;i<pos;i++)
9331     pool[i]=_pool[i];
9332   for(std::size_t j=0;j<sz;j++)
9333     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9334   for(int i=pos+1;i<(int)_pool.size();i++)
9335     pool[i+sz-1]=_pool[i];
9336   _pool=pool;
9337   //
9338   if(sz==2)
9339     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9340   //
9341   if(isFast)
9342     {
9343       _ze_mesh=mesh;
9344       return ;
9345     }
9346   //
9347   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9348   if(pos>0)
9349     {
9350       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9351       ms.push_back(elt);
9352     }
9353   ms.push_back(mesh);
9354   if(pos<_ze_mesh->getNumberOfCells()-1)
9355   {
9356     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9357     ms.push_back(elt);
9358   }
9359   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9360   for(std::size_t j=0;j<ms2.size();j++)
9361     ms2[j]=ms[j];
9362   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9363 }
9364
9365 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9366 {
9367   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9368 }
9369
9370 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9371 {
9372   if(pos<0)
9373     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9374   int ret(0);
9375   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9376     {
9377       if((*it).isInMyRange(pos))
9378         return ret;
9379     }
9380   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9381 }
9382
9383 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9384 {
9385   get(pos);//to check;
9386   if(_edge_info.empty())
9387     return ;
9388   std::size_t sz(_edge_info.size()-1);
9389   for(std::size_t i=0;i<sz;i++)
9390     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9391 }
9392
9393 const CellInfo& VectorOfCellInfo::get(int pos) const
9394 {
9395   if(pos<0 || pos>=(int)_pool.size())
9396     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9397   return _pool[pos];
9398 }
9399
9400 CellInfo& VectorOfCellInfo::get(int pos)
9401 {
9402   if(pos<0 || pos>=(int)_pool.size())
9403     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9404   return _pool[pos];
9405 }
9406
9407 /*!
9408  * Given :
9409  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9410  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9411  *
9412  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9413  *
9414  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9415  *
9416  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9417  */
9418 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9419                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9420 {
9421   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9422   if(nbCellsInSplitMesh1D==0)
9423     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9424   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9425   std::size_t nb(allEdges.size()),jj;
9426   if(nb%2!=0)
9427     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9428   std::vector<int> edge1Bis(nb*2);
9429   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9430   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9431   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9432   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9433   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9434   //
9435   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9436   int *idsLeftRightPtr(idsLeftRight->getPointer());
9437   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9438   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9439     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9440       int iEnd(iStart);
9441       for(;iEnd<nbCellsInSplitMesh1D;)
9442         {
9443           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9444           if(jj!=nb)
9445             break;
9446           else
9447             iEnd++;
9448         }
9449       if(iEnd<nbCellsInSplitMesh1D)
9450         iEnd++;
9451       //
9452       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9453       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9454       //
9455       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9456       retTmp->setCoords(splitMesh1D->getCoords());
9457       retTmp->allocateCells();
9458
9459       std::vector< std::vector<int> > out0;
9460       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9461
9462       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9463       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9464         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9465       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9466       //
9467       iStart=iEnd;
9468     }
9469   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9470     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9471   return pool.getZeMesh().retn();
9472 }
9473
9474 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9475                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9476                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9477 {
9478   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9479   //
9480   std::vector<int> allEdges;
9481   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9482   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9483     {
9484       int edgeId(std::abs(*it)-1);
9485       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9486       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9487       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9488       if(*it>0)
9489         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9490       else
9491         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9492       std::size_t sz(edge1.size());
9493       for(std::size_t cnt=0;cnt<sz;cnt++)
9494         allEdgesPtr.push_back(ee);
9495     }
9496   //
9497   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9498 }
9499
9500 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9501 {
9502   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9503     {//easy case comparison not
9504       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9505     }
9506   else if(typ1.isQuadratic() && typ2.isQuadratic())
9507     {
9508       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9509       if(!status0)
9510         return false;
9511       if(conn1[2]==conn2[2])
9512         return true;
9513       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9514       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9515       return dist<eps;
9516     }
9517   else
9518     {//only one is quadratic
9519       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9520       if(!status0)
9521         return false;
9522       const double *a(0),*bb(0),*be(0);
9523       if(typ1.isQuadratic())
9524         {
9525           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9526         }
9527       else
9528         {
9529           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9530         }
9531       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9532       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9533       return dist<eps;
9534     }
9535 }
9536
9537 /*!
9538  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9539  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9540  *
9541  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9542  */
9543 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9544 {
9545   if(candidatesIn2DEnd==candidatesIn2DBg)
9546     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9547   const double *coo(mesh2DSplit->getCoords()->begin());
9548   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9549     return *candidatesIn2DBg;
9550   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9551   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9552   if(cellIdInMesh1DSplitRelative<0)
9553     cur1D->changeOrientationOfCells();
9554   const int *c1D(cur1D->getNodalConnectivity()->begin());
9555   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9556   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9557     {
9558       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9559       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9560       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9561       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9562       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9563       for(unsigned it2=0;it2<sz;it2++)
9564         {
9565           INTERP_KERNEL::NormalizedCellType typeOfSon;
9566           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9567           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9568           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9569             return *it;
9570         }
9571     }
9572   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9573 }
9574
9575 /// @endcond
9576
9577 /*!
9578  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9579  * 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
9580  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9581  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9582  *
9583  * \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
9584  *                      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)
9585  * \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
9586  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9587  * \param [in] eps - precision used to perform intersections and localization operations.
9588  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9589  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9590  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9591  *                               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.
9592  * \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
9593  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9594  *                               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.
9595  *
9596  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9597  */
9598 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9599 {
9600   if(!mesh2D || !mesh1D)
9601     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9602   mesh2D->checkFullyDefined();
9603   mesh1D->checkFullyDefined();
9604   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9605   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9606     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9607   // Step 1: compute all edge intersections (new nodes)
9608   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9609   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9610   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9611   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9612   //
9613   // Build desc connectivity
9614   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9615   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9616   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9617   std::map<int,int> mergedNodes;
9618   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9619   // use mergeNodes to fix intersectEdge1
9620   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9621     {
9622       std::size_t n((*it0).size()/2);
9623       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9624       std::map<int,int>::const_iterator it1;
9625       it1=mergedNodes.find(eltStart);
9626       if(it1!=mergedNodes.end())
9627         (*it0)[0]=(*it1).second;
9628       it1=mergedNodes.find(eltEnd);
9629       if(it1!=mergedNodes.end())
9630         (*it0)[2*n-1]=(*it1).second;
9631     }
9632   //
9633   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9634   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9635   // Step 2: re-order newly created nodes according to the ordering found in m2
9636   std::vector< std::vector<int> > intersectEdge2;
9637   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9638   subDiv2.clear();
9639   // Step 3: compute splitMesh1D
9640   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9641   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9642   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9643       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9644   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9645   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9646   // deal with cells in mesh2D that are not cut but only some of their edges are
9647   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9648   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9649   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9650   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
9651   if(!idsInDesc2DToBeRefined->empty())
9652     {
9653       DataArrayInt *out0(0),*outi0(0);
9654       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9655       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9656       out0s=out0;
9657       out0s=out0s->buildUnique();
9658       out0s->sort(true);
9659     }
9660   //
9661   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9662   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9663   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9664   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9665   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9666   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9667   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9668     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9669   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9670   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9671   if((DataArrayInt *)out0s)
9672     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9673   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9674   // OK all is ready to insert in ret2 mesh
9675   if(!untouchedCells->empty())
9676     {// the most easy part, cells in mesh2D not impacted at all
9677       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9678       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9679       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9680     }
9681   if((DataArrayInt *)out0s)
9682     {// here dealing with cells in out0s but not in cellsToBeModified
9683       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9684       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9685       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9686         {
9687           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9688           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9689         }
9690       int offset(ret2->getNumberOfTuples());
9691       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9692       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9693       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9694       int kk(0),*ret3ptr(partOfRet3->getPointer());
9695       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9696         {
9697           int faceId(std::abs(*it)-1);
9698           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9699             {
9700               int tmp(fewModifiedCells->locateValue(*it2));
9701               if(tmp!=-1)
9702                 {
9703                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9704                     ret3ptr[2*kk]=tmp+offset;
9705                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9706                     ret3ptr[2*kk+1]=tmp+offset;
9707                 }
9708               else
9709                 {//the current edge is shared by a 2D cell that will be split just after
9710                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9711                     ret3ptr[2*kk]=-(*it2+1);
9712                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9713                     ret3ptr[2*kk+1]=-(*it2+1);
9714                 }
9715             }
9716         }
9717       m1Desc->setCoords(ret1->getCoords());
9718       ret1NonCol->setCoords(ret1->getCoords());
9719       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9720       if(!outMesh2DSplit.empty())
9721         {
9722           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9723           for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9724             (*itt)->setCoords(da);
9725         }
9726     }
9727   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9728   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9729     {
9730       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9731       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9732       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9733       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9734       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9735       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));
9736       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9737       outMesh2DSplit.push_back(splitOfOneCell);
9738       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9739         ret2->pushBackSilent(*it);
9740     }
9741   //
9742   std::size_t nbOfMeshes(outMesh2DSplit.size());
9743   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9744   for(std::size_t i=0;i<nbOfMeshes;i++)
9745     tmp[i]=outMesh2DSplit[i];
9746   //
9747   ret1->getCoords()->setInfoOnComponents(compNames);
9748   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9749   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9750   ret3->rearrange(1);
9751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9752   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9753     {
9754       int old2DCellId(-ret3->getIJ(*it,0)-1);
9755       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9756       ret3->setIJ(*it,0,FindRightCandidateAmong(ret2D,candidates->begin(),candidates->end(),ret1,*it%2==0?-((*it)/2+1):(*it)/2+1,eps));// div by 2 because 2 components natively in ret3
9757     }
9758   ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9759   ret3->rearrange(2);
9760   //
9761   splitMesh1D=ret1.retn();
9762   splitMesh2D=ret2D.retn();
9763   cellIdInMesh2D=ret2.retn();
9764   cellIdInMesh1D=ret3.retn();
9765 }
9766
9767 /**
9768  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9769  * (newly created) nodes corresponding to the edge intersections.
9770  * Output params:
9771  * @param[out] cr, crI connectivity of the resulting mesh
9772  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9773  * TODO: describe input parameters
9774  */
9775 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9776                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9777                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9778                                                          const std::vector<double>& addCoords,
9779                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9780 {
9781   static const int SPACEDIM=2;
9782   const double *coo1(m1->getCoords()->getConstPointer());
9783   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9784   int offset1(m1->getNumberOfNodes());
9785   const double *coo2(m2->getCoords()->getConstPointer());
9786   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9787   int offset2(offset1+m2->getNumberOfNodes());
9788   int offset3(offset2+((int)addCoords.size())/2);
9789   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9790   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9791   // Here a BBTree on 2D-cells, not on segments:
9792   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9793   int ncell1(m1->getNumberOfCells());
9794   crI.push_back(0);
9795   for(int i=0;i<ncell1;i++)
9796     {
9797       std::vector<int> candidates2;
9798       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9799       std::map<INTERP_KERNEL::Node *,int> mapp;
9800       std::map<int,INTERP_KERNEL::Node *> mappRev;
9801       INTERP_KERNEL::QuadraticPolygon pol1;
9802       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9803       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9804       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9805       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9806       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9807       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9808           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9809       //
9810       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
9811       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9812       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9813       for(it1.first();!it1.finished();it1.next())
9814         edges1.insert(it1.current()->getPtr());
9815       //
9816       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9817       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9818       int ii=0;
9819       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9820         {
9821           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9822           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9823           // Complete mapping with elements coming from the current cell it2 in mesh2:
9824           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9825           // pol2 is the new QP in the final merged result.
9826           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9827               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9828         }
9829       ii=0;
9830       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9831         {
9832           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9833           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9834           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9835           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9836         }
9837       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9838       // by m2 but that we still want to keep in the final result.
9839       if(!edges1.empty())
9840         {
9841           try
9842           {
9843               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9844           }
9845           catch(INTERP_KERNEL::Exception& e)
9846           {
9847               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();
9848               throw INTERP_KERNEL::Exception(oss.str().c_str());
9849           }
9850         }
9851       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9852         (*it).second->decrRef();
9853     }
9854 }
9855
9856 /**
9857  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9858  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9859  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9860  * The caller is to deal with the resulting DataArrayInt.
9861  *  \throw If the coordinate array is not set.
9862  *  \throw If the nodal connectivity of the cells is not defined.
9863  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9864  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9865  *
9866  * \sa DataArrayInt::sortEachPairToMakeALinkedList
9867  */
9868 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9869 {
9870   checkFullyDefined();
9871   if(getMeshDimension()!=1)
9872     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9873
9874   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9875   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9877   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9878   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9879   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9881   const int * dsi(_dsi->getConstPointer());
9882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9883   m_points=0;
9884   if (dsii->getNumberOfTuples())
9885     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9886
9887   int nc(getNumberOfCells());
9888   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9889   result->alloc(nc,1);
9890
9891   // set of edges not used so far
9892   std::set<int> edgeSet;
9893   for (int i=0; i<nc; edgeSet.insert(i), i++);
9894
9895   int startSeg=0;
9896   int newIdx=0;
9897   // while we have points with only one neighbor segments
9898   do
9899     {
9900       std::list<int> linePiece;
9901       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9902       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9903         {
9904           // Fill the list forward (resp. backward) from the start segment:
9905           int activeSeg = startSeg;
9906           int prevPointId = -20;
9907           int ptId;
9908           while (!edgeSet.empty())
9909             {
9910               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9911                 {
9912                   if (direction==0)
9913                     linePiece.push_back(activeSeg);
9914                   else
9915                     linePiece.push_front(activeSeg);
9916                   edgeSet.erase(activeSeg);
9917                 }
9918
9919               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9920               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9921               if (dsi[ptId] == 1) // hitting the end of the line
9922                 break;
9923               prevPointId = ptId;
9924               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9925               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9926             }
9927         }
9928       // Done, save final piece into DA:
9929       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9930       newIdx += linePiece.size();
9931
9932       // identify next valid start segment (one which is not consumed)
9933       if(!edgeSet.empty())
9934         startSeg = *(edgeSet.begin());
9935     }
9936   while (!edgeSet.empty());
9937   return result.retn();
9938 }
9939
9940 /// @cond INTERNAL
9941
9942 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9943 {
9944   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9945   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9946   if(it==m.end())
9947     throw INTERP_KERNEL::Exception("Internal error in remapping !");
9948   int v((*it).second);
9949   if(v==forbVal0 || v==forbVal1)
9950     return ;
9951   if(std::find(isect.begin(),isect.end(),v)==isect.end())
9952     isect.push_back(v);
9953 }
9954
9955 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9956 {
9957   int sz(c.size());
9958   if(sz<=1)
9959     return false;
9960   bool presenceOfOn(false);
9961   for(int i=0;i<sz;i++)
9962     {
9963       INTERP_KERNEL::ElementaryEdge *e(c[i]);
9964       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9965         continue ;
9966       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9967       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9968     }
9969   return presenceOfOn;
9970 }
9971
9972 /// @endcond
9973
9974 /**
9975  * 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.
9976  * 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.
9977  * 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.
9978  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
9979  *
9980  * \return int - the number of new nodes created (in most of cases 0).
9981  * 
9982  * \throw If \a this is not coherent.
9983  * \throw If \a this has not spaceDim equal to 2.
9984  * \throw If \a this has not meshDim equal to 2.
9985  * \throw If some subcells needed to be split are orphan.
9986  * \sa MEDCouplingUMesh::conformize2D
9987  */
9988 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9989 {
9990   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9991     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9992   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9993   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9994     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9995   if(midOpt==0 && midOptI==0)
9996     {
9997       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
9998       return 0;
9999     }
10000   else if(midOpt!=0 && midOptI!=0)
10001     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10002   else
10003     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10004 }
10005
10006 /*!
10007  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10008  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10009  * 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
10010  * 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).
10011  * 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.
10012  * 
10013  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10014  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10015  *
10016  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10017  * This method expects that all nodes in \a this are not closer than \a eps.
10018  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10019  * 
10020  * \param [in] eps the relative error to detect merged edges.
10021  * \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
10022  *                           that the user is expected to deal with.
10023  *
10024  * \throw If \a this is not coherent.
10025  * \throw If \a this has not spaceDim equal to 2.
10026  * \throw If \a this has not meshDim equal to 2.
10027  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10028  */
10029 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10030 {
10031   static const int SPACEDIM=2;
10032   checkCoherency();
10033   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10034     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10035   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10036   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10037   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10038   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10039   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10040   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10041   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10042   std::vector<double> addCoo;
10043   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10044   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10045   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10046   for(int i=0;i<nDescCell;i++)
10047     {
10048       std::vector<int> candidates;
10049       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10050       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10051         if(*it>i)
10052           {
10053             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10054             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10055                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10056             INTERP_KERNEL::MergePoints merge;
10057             INTERP_KERNEL::QuadraticPolygon c1,c2;
10058             e1->intersectWith(e2,merge,c1,c2);
10059             e1->decrRef(); e2->decrRef();
10060             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10061               overlapEdge[i].push_back(*it);
10062             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10063               overlapEdge[*it].push_back(i);
10064           }
10065     }
10066   // splitting done. sort intersect point in intersectEdge.
10067   std::vector< std::vector<int> > middle(nDescCell);
10068   int nbOf2DCellsToBeSplit(0);
10069   bool middleNeedsToBeUsed(false);
10070   std::vector<bool> cells2DToTreat(nDescCell,false);
10071   for(int i=0;i<nDescCell;i++)
10072     {
10073       std::vector<int>& isect(intersectEdge[i]);
10074       int sz((int)isect.size());
10075       if(sz>1)
10076         {
10077           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10078           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10079           e->sortSubNodesAbs(coords,isect);
10080           e->decrRef();
10081         }
10082       if(sz!=0)
10083         {
10084           int idx0(rdi[i]),idx1(rdi[i+1]);
10085           if(idx1-idx0!=1)
10086             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10087           if(!cells2DToTreat[rd[idx0]])
10088             {
10089               cells2DToTreat[rd[idx0]]=true;
10090               nbOf2DCellsToBeSplit++;
10091             }
10092           // try to reuse at most eventual 'middle' of SEG3
10093           std::vector<int>& mid(middle[i]);
10094           mid.resize(sz+1,-1);
10095           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10096             {
10097               middleNeedsToBeUsed=true;
10098               const std::vector<int>& candidates(overlapEdge[i]);
10099               std::vector<int> trueCandidates;
10100               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10101                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10102                   trueCandidates.push_back(*itc);
10103               int stNode(c[ci[i]+1]),endNode(isect[0]);
10104               for(int j=0;j<sz+1;j++)
10105                 {
10106                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10107                     {
10108                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10109                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10110                         { mid[j]=*itc; break; }
10111                     }
10112                   stNode=endNode;
10113                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10114                 }
10115             }
10116         }
10117     }
10118   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10119   if(nbOf2DCellsToBeSplit==0)
10120     return ret.retn();
10121   //
10122   int *retPtr(ret->getPointer());
10123   for(int i=0;i<nCell;i++)
10124     if(cells2DToTreat[i])
10125       *retPtr++=i;
10126   //
10127   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10128   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10129   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10130   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10131   if(middleNeedsToBeUsed)
10132     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10133   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10134   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10135   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.
10136   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10137   {
10138     bool areNodesMerged; int newNbOfNodes;
10139     if(nbOfNodesCreated!=0)
10140       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10141   }
10142   return ret.retn();
10143 }
10144
10145 /*!
10146  * 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.
10147  * 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).
10148  * 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
10149  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10150  * 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
10151  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10152  *
10153  * 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
10154  * using new instance, idem for coordinates.
10155  *
10156  * 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.
10157  * 
10158  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10159  *
10160  * \throw If \a this is not coherent.
10161  * \throw If \a this has not spaceDim equal to 2.
10162  * \throw If \a this has not meshDim equal to 2.
10163  * 
10164  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10165  */
10166 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10167 {
10168   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10169   checkCoherency();
10170   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10171     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10172   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10173   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10174   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10175   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10176   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10177   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10178   const double *coords(_coords->begin());
10179   int *newciptr(newci->getPointer());
10180   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10181     {
10182       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10183         ret->pushBackSilent(i);
10184       newciptr[1]=newc->getNumberOfTuples();
10185     }
10186   //
10187   if(ret->empty())
10188     return ret.retn();
10189   if(!appendedCoords->empty())
10190     {
10191       appendedCoords->rearrange(2);
10192       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10193       //non const part
10194       setCoords(newCoords);
10195     }
10196   //non const part
10197   setConnectivity(newc,newci,true);
10198   return ret.retn();
10199 }
10200
10201 /*!
10202  * \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.
10203  *                               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.
10204  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10205  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10206  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10207  * \param [out] addCoo - nodes to be append at the end
10208  * \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.
10209  */
10210 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10211                                          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)
10212 {
10213   static const int SPACEDIM=2;
10214   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10215   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10216   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10217   // Build BB tree of all edges in the tool mesh (second mesh)
10218   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10219   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10220   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10221   intersectEdge1.resize(nDescCell1);
10222   colinear2.resize(nDescCell2);
10223   subDiv2.resize(nDescCell2);
10224   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10225
10226   std::vector<int> candidates1(1);
10227   int offset1(m1Desc->getNumberOfNodes());
10228   int offset2(offset1+m2Desc->getNumberOfNodes());
10229   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10230     {
10231       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10232       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10233       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10234         {
10235           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10236           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10237           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10238           candidates1[0]=i;
10239           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10240           // 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
10241           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10242           std::set<INTERP_KERNEL::Node *> nodes;
10243           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10244           std::size_t szz(nodes.size());
10245           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10246           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10247           for(std::size_t iii=0;iii<szz;iii++,itt++)
10248             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10249           // end of protection
10250           // Performs egde cutting:
10251           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10252           delete pol2;
10253           delete pol1;
10254         }
10255       else
10256         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10257         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10258     }
10259 }
10260
10261 /*!
10262  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10263  * It builds the descending connectivity of the two meshes, and then using a binary tree
10264  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10265  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10266  */
10267 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10268                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10269                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10270                                                    std::vector<double>& addCoo,
10271                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10272 {
10273   // Build desc connectivity
10274   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10275   desc2=DataArrayInt::New();
10276   descIndx2=DataArrayInt::New();
10277   revDesc2=DataArrayInt::New();
10278   revDescIndx2=DataArrayInt::New();
10279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10281   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10282   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10283   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10284   std::map<int,int> notUsedMap;
10285   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10286   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10287   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10288 }
10289
10290 /*!
10291  * This method performs the 2nd step of Partition of 2D mesh.
10292  * This method has 4 inputs :
10293  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10294  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10295  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10296  * 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'
10297  * Nodes end up lying consecutively on a cutted edge.
10298  * \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.
10299  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10300  * \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.
10301  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10302  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10303  */
10304 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10305                                            const std::vector<double>& addCoo,
10306                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10307 {
10308   int offset1=m1->getNumberOfNodes();
10309   int ncell=m2->getNumberOfCells();
10310   const int *c=m2->getNodalConnectivity()->getConstPointer();
10311   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10312   const double *coo=m2->getCoords()->getConstPointer();
10313   const double *cooBis=m1->getCoords()->getConstPointer();
10314   int offset2=offset1+m2->getNumberOfNodes();
10315   intersectEdge.resize(ncell);
10316   for(int i=0;i<ncell;i++,cI++)
10317     {
10318       const std::vector<int>& divs=subDiv[i];
10319       int nnode=cI[1]-cI[0]-1;
10320       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10321       std::map<INTERP_KERNEL::Node *, int> mapp22;
10322       for(int j=0;j<nnode;j++)
10323         {
10324           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10325           int nnid=c[(*cI)+j+1];
10326           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10327           mapp22[nn]=nnid+offset1;
10328         }
10329       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10330       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10331         ((*it).second.first)->decrRef();
10332       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10333       std::map<INTERP_KERNEL::Node *,int> mapp3;
10334       for(std::size_t j=0;j<divs.size();j++)
10335         {
10336           int id=divs[j];
10337           INTERP_KERNEL::Node *tmp=0;
10338           if(id<offset1)
10339             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10340           else if(id<offset2)
10341             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10342           else
10343             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10344           addNodes[j]=tmp;
10345           mapp3[tmp]=id;
10346         }
10347       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10348       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10349         (*it)->decrRef();
10350       e->decrRef();
10351     }
10352 }
10353
10354 /*!
10355  * 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).
10356  * 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
10357  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10358  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10359  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10360  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10361  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10362  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10363  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10364  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10365  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10366  * \param [out] cut3DSuf input/output param.
10367  */
10368 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10369                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10370                                                    const int *desc, const int *descIndx, 
10371                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10372 {
10373   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10374   int nbOf3DSurfCell=(int)cut3DSurf.size();
10375   for(int i=0;i<nbOf3DSurfCell;i++)
10376     {
10377       std::vector<int> res;
10378       int offset=descIndx[i];
10379       int nbOfSeg=descIndx[i+1]-offset;
10380       for(int j=0;j<nbOfSeg;j++)
10381         {
10382           int edgeId=desc[offset+j];
10383           int status=cut3DCurve[edgeId];
10384           if(status!=-2)
10385             {
10386               if(status>-1)
10387                 res.push_back(status);
10388               else
10389                 {
10390                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10391                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10392                 }
10393             }
10394         }
10395       switch(res.size())
10396       {
10397         case 2:
10398           {
10399             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10400             break;
10401           }
10402         case 1:
10403         case 0:
10404           {
10405             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10406             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10407             if(res.size()==2)
10408               {
10409                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10410               }
10411             else
10412               {
10413                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10414               }
10415             break;
10416           }
10417         default:
10418           {// case when plane is on a multi colinear edge of a polyhedron
10419             if((int)res.size()==2*nbOfSeg)
10420               {
10421                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10422               }
10423             else
10424               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10425           }
10426       }
10427     }
10428 }
10429
10430 /*!
10431  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10432  * 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).
10433  * 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
10434  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10435  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10436  * \param desc is the descending connectivity 3D->3DSurf
10437  * \param descIndx is the descending connectivity index 3D->3DSurf
10438  */
10439 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10440                                                   const int *desc, const int *descIndx,
10441                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10442 {
10443   checkFullyDefined();
10444   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10445     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10446   const int *nodal3D=_nodal_connec->getConstPointer();
10447   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10448   int nbOfCells=getNumberOfCells();
10449   for(int i=0;i<nbOfCells;i++)
10450     {
10451       std::map<int, std::set<int> > m;
10452       int offset=descIndx[i];
10453       int nbOfFaces=descIndx[i+1]-offset;
10454       int start=-1;
10455       int end=-1;
10456       for(int j=0;j<nbOfFaces;j++)
10457         {
10458           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10459           if(p.first!=-1 && p.second!=-1)
10460             {
10461               if(p.first!=-2)
10462                 {
10463                   start=p.first; end=p.second;
10464                   m[p.first].insert(p.second);
10465                   m[p.second].insert(p.first);
10466                 }
10467               else
10468                 {
10469                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10470                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10471                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10472                   INTERP_KERNEL::NormalizedCellType cmsId;
10473                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10474                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10475                   for(unsigned k=0;k<nbOfNodesSon;k++)
10476                     {
10477                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10478                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10479                     }
10480                 }
10481             }
10482         }
10483       if(m.empty())
10484         continue;
10485       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10486       int prev=end;
10487       while(end!=start)
10488         {
10489           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10490           const std::set<int>& s=(*it).second;
10491           std::set<int> s2; s2.insert(prev);
10492           std::set<int> s3;
10493           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10494           if(s3.size()==1)
10495             {
10496               int val=*s3.begin();
10497               conn.push_back(start);
10498               prev=start;
10499               start=val;
10500             }
10501           else
10502             start=end;
10503         }
10504       conn.push_back(end);
10505       if(conn.size()>3)
10506         {
10507           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10508           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10509           cellIds->pushBackSilent(i);
10510         }
10511     }
10512 }
10513
10514 /*!
10515  * 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
10516  * 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
10517  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10518  * 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
10519  * 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.
10520  * 
10521  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10522  */
10523 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10524 {
10525   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10526   if(sz>=4)
10527     {
10528       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10529       if(cm.getDimension()==2)
10530         {
10531           const int *node=nodalConnBg+1;
10532           int startNode=*node++;
10533           double refX=coords[2*startNode];
10534           for(;node!=nodalConnEnd;node++)
10535             {
10536               if(coords[2*(*node)]<refX)
10537                 {
10538                   startNode=*node;
10539                   refX=coords[2*startNode];
10540                 }
10541             }
10542           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10543           refX=1e300;
10544           double tmp1;
10545           double tmp2[2];
10546           double angle0=-M_PI/2;
10547           //
10548           int nextNode=-1;
10549           int prevNode=-1;
10550           double resRef;
10551           double angleNext=0.;
10552           while(nextNode!=startNode)
10553             {
10554               nextNode=-1;
10555               resRef=1e300;
10556               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10557                 {
10558                   if(*node!=tmpOut.back() && *node!=prevNode)
10559                     {
10560                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10561                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10562                       double res;
10563                       if(angleM<=angle0)
10564                         res=angle0-angleM;
10565                       else
10566                         res=angle0-angleM+2.*M_PI;
10567                       if(res<resRef)
10568                         {
10569                           nextNode=*node;
10570                           resRef=res;
10571                           angleNext=angleM;
10572                         }
10573                     }
10574                 }
10575               if(nextNode!=startNode)
10576                 {
10577                   angle0=angleNext-M_PI;
10578                   if(angle0<-M_PI)
10579                     angle0+=2*M_PI;
10580                   prevNode=tmpOut.back();
10581                   tmpOut.push_back(nextNode);
10582                 }
10583             }
10584           std::vector<int> tmp3(2*(sz-1));
10585           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10586           std::copy(nodalConnBg+1,nodalConnEnd,it);
10587           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10588             {
10589               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10590               return false;
10591             }
10592           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10593             {
10594               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10595               return false;
10596             }
10597           else
10598             {
10599               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10600               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10601               return true;
10602             }
10603         }
10604       else
10605         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10606     }
10607   else
10608     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10609 }
10610
10611 /*!
10612  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10613  * 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.
10614  * 
10615  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10616  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10617  * \param [in,out] arr array in which the remove operation will be done.
10618  * \param [in,out] arrIndx array in the remove operation will modify
10619  * \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])
10620  * \return true if \b arr and \b arrIndx have been modified, false if not.
10621  */
10622 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10623 {
10624   if(!arrIndx || !arr)
10625     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10626   if(offsetForRemoval<0)
10627     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10628   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10629   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10630   int *arrIPtr=arrIndx->getPointer();
10631   *arrIPtr++=0;
10632   int previousArrI=0;
10633   const int *arrPtr=arr->getConstPointer();
10634   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10635   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10636     {
10637       if(*arrIPtr-previousArrI>offsetForRemoval)
10638         {
10639           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10640             {
10641               if(s.find(*work)==s.end())
10642                 arrOut.push_back(*work);
10643             }
10644         }
10645       previousArrI=*arrIPtr;
10646       *arrIPtr=(int)arrOut.size();
10647     }
10648   if(arr->getNumberOfTuples()==(int)arrOut.size())
10649     return false;
10650   arr->alloc((int)arrOut.size(),1);
10651   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10652   return true;
10653 }
10654
10655 /*!
10656  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10657  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10658  * The selection of extraction is done standardly in new2old format.
10659  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10660  *
10661  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10662  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10663  * \param [in] arrIn arr origin array from which the extraction will be done.
10664  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10665  * \param [out] arrOut the resulting array
10666  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10667  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10668  */
10669 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10670                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10671 {
10672   if(!arrIn || !arrIndxIn)
10673     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10674   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10675   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10676     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10677   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10678   const int *arrInPtr=arrIn->getConstPointer();
10679   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10680   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10681   if(nbOfGrps<0)
10682     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10683   int maxSizeOfArr=arrIn->getNumberOfTuples();
10684   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10685   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10686   arrIo->alloc((int)(sz+1),1);
10687   const int *idsIt=idsOfSelectBg;
10688   int *work=arrIo->getPointer();
10689   *work++=0;
10690   int lgth=0;
10691   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10692     {
10693       if(*idsIt>=0 && *idsIt<nbOfGrps)
10694         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10695       else
10696         {
10697           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10698           throw INTERP_KERNEL::Exception(oss.str().c_str());
10699         }
10700       if(lgth>=work[-1])
10701         *work=lgth;
10702       else
10703         {
10704           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10705           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10706           throw INTERP_KERNEL::Exception(oss.str().c_str());
10707         }
10708     }
10709   arro->alloc(lgth,1);
10710   work=arro->getPointer();
10711   idsIt=idsOfSelectBg;
10712   for(std::size_t i=0;i<sz;i++,idsIt++)
10713     {
10714       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10715         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10716       else
10717         {
10718           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10719           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10720           throw INTERP_KERNEL::Exception(oss.str().c_str());
10721         }
10722     }
10723   arrOut=arro.retn();
10724   arrIndexOut=arrIo.retn();
10725 }
10726
10727 /*!
10728  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10729  * 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 ).
10730  * The selection of extraction is done standardly in new2old format.
10731  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10732  *
10733  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10734  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10735  * \param [in] arrIn arr origin array from which the extraction will be done.
10736  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10737  * \param [out] arrOut the resulting array
10738  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10739  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10740  */
10741 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10742                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10743 {
10744   if(!arrIn || !arrIndxIn)
10745     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10746   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10747   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10748     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10749   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10750   const int *arrInPtr=arrIn->getConstPointer();
10751   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10752   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10753   if(nbOfGrps<0)
10754     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10755   int maxSizeOfArr=arrIn->getNumberOfTuples();
10756   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10757   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10758   arrIo->alloc((int)(sz+1),1);
10759   int idsIt=idsOfSelectStart;
10760   int *work=arrIo->getPointer();
10761   *work++=0;
10762   int lgth=0;
10763   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10764     {
10765       if(idsIt>=0 && idsIt<nbOfGrps)
10766         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10767       else
10768         {
10769           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10770           throw INTERP_KERNEL::Exception(oss.str().c_str());
10771         }
10772       if(lgth>=work[-1])
10773         *work=lgth;
10774       else
10775         {
10776           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10777           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10778           throw INTERP_KERNEL::Exception(oss.str().c_str());
10779         }
10780     }
10781   arro->alloc(lgth,1);
10782   work=arro->getPointer();
10783   idsIt=idsOfSelectStart;
10784   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10785     {
10786       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10787         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10788       else
10789         {
10790           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10791           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10792           throw INTERP_KERNEL::Exception(oss.str().c_str());
10793         }
10794     }
10795   arrOut=arro.retn();
10796   arrIndexOut=arrIo.retn();
10797 }
10798
10799 /*!
10800  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10801  * 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
10802  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10803  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10804  *
10805  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10806  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10807  * \param [in] arrIn arr origin array from which the extraction will be done.
10808  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10809  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10810  * \param [in] srcArrIndex index array of \b srcArr
10811  * \param [out] arrOut the resulting array
10812  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10813  * 
10814  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10815  */
10816 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10817                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10818                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10819 {
10820   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10821     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10823   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10824   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10825   std::vector<bool> v(nbOfTuples,true);
10826   int offset=0;
10827   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10828   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10829   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10830     {
10831       if(*it>=0 && *it<nbOfTuples)
10832         {
10833           v[*it]=false;
10834           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10835         }
10836       else
10837         {
10838           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10839           throw INTERP_KERNEL::Exception(oss.str().c_str());
10840         }
10841     }
10842   srcArrIndexPtr=srcArrIndex->getConstPointer();
10843   arrIo->alloc(nbOfTuples+1,1);
10844   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10845   const int *arrInPtr=arrIn->getConstPointer();
10846   const int *srcArrPtr=srcArr->getConstPointer();
10847   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10848   int *arroPtr=arro->getPointer();
10849   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10850     {
10851       if(v[ii])
10852         {
10853           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10854           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10855         }
10856       else
10857         {
10858           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10859           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10860           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10861         }
10862     }
10863   arrOut=arro.retn();
10864   arrIndexOut=arrIo.retn();
10865 }
10866
10867 /*!
10868  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10869  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10870  *
10871  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10872  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10873  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10874  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10875  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10876  * \param [in] srcArrIndex index array of \b srcArr
10877  * 
10878  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10879  */
10880 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10881                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10882 {
10883   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10884     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10885   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10886   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10887   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10888   int *arrInOutPtr=arrInOut->getPointer();
10889   const int *srcArrPtr=srcArr->getConstPointer();
10890   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10891     {
10892       if(*it>=0 && *it<nbOfTuples)
10893         {
10894           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10895             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10896           else
10897             {
10898               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] !";
10899               throw INTERP_KERNEL::Exception(oss.str().c_str());
10900             }
10901         }
10902       else
10903         {
10904           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10905           throw INTERP_KERNEL::Exception(oss.str().c_str());
10906         }
10907     }
10908 }
10909
10910 /*!
10911  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10912  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10913  * 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]].
10914  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10915  * A negative value in \b arrIn means that it is ignored.
10916  * 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.
10917  * 
10918  * \param [in] arrIn arr origin array from which the extraction will be done.
10919  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10920  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10921  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10922  */
10923 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10924 {
10925   int seed=0,nbOfDepthPeelingPerformed=0;
10926   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10927 }
10928
10929 /*!
10930  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10931  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10932  * 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]].
10933  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10934  * A negative value in \b arrIn means that it is ignored.
10935  * 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.
10936  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10937  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10938  * \param [in] arrIn arr origin array from which the extraction will be done.
10939  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10940  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10941  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10942  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10943  * \sa MEDCouplingUMesh::partitionBySpreadZone
10944  */
10945 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10946 {
10947   nbOfDepthPeelingPerformed=0;
10948   if(!arrIndxIn)
10949     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10950   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10951   if(nbOfTuples<=0)
10952     {
10953       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10954       return ret;
10955     }
10956   //
10957   std::vector<bool> fetched(nbOfTuples,false);
10958   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10959 }
10960
10961 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10962 {
10963   nbOfDepthPeelingPerformed=0;
10964   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10965     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10966   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10967   std::vector<bool> fetched2(nbOfTuples,false);
10968   int i=0;
10969   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10970     {
10971       if(*seedElt>=0 && *seedElt<nbOfTuples)
10972         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10973       else
10974         { 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()); }
10975     }
10976   const int *arrInPtr=arrIn->getConstPointer();
10977   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10978   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
10979   std::vector<int> idsToFetch1(seedBg,seedEnd);
10980   std::vector<int> idsToFetch2;
10981   std::vector<int> *idsToFetch=&idsToFetch1;
10982   std::vector<int> *idsToFetchOther=&idsToFetch2;
10983   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
10984     {
10985       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
10986         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
10987           if(!fetched[*it2])
10988             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10989       std::swap(idsToFetch,idsToFetchOther);
10990       idsToFetchOther->clear();
10991       nbOfDepthPeelingPerformed++;
10992     }
10993   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10994   i=0;
10995   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10996   int *retPtr=ret->getPointer();
10997   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
10998     if(*it)
10999       *retPtr++=i;
11000   return ret.retn();
11001 }
11002
11003 /*!
11004  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11005  * 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
11006  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11007  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11008  *
11009  * \param [in] start begin of set of ids of the input extraction (included)
11010  * \param [in] end end of set of ids of the input extraction (excluded)
11011  * \param [in] step step of the set of ids in range mode.
11012  * \param [in] arrIn arr origin array from which the extraction will be done.
11013  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11014  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11015  * \param [in] srcArrIndex index array of \b srcArr
11016  * \param [out] arrOut the resulting array
11017  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11018  * 
11019  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11020  */
11021 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11022                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11023                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11024 {
11025   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11026     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11027   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11028   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11029   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11030   int offset=0;
11031   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11032   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11033   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11034   int it=start;
11035   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11036     {
11037       if(it>=0 && it<nbOfTuples)
11038         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11039       else
11040         {
11041           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11042           throw INTERP_KERNEL::Exception(oss.str().c_str());
11043         }
11044     }
11045   srcArrIndexPtr=srcArrIndex->getConstPointer();
11046   arrIo->alloc(nbOfTuples+1,1);
11047   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11048   const int *arrInPtr=arrIn->getConstPointer();
11049   const int *srcArrPtr=srcArr->getConstPointer();
11050   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11051   int *arroPtr=arro->getPointer();
11052   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11053     {
11054       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11055       if(pos<0)
11056         {
11057           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11058           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11059         }
11060       else
11061         {
11062           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11063           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11064         }
11065     }
11066   arrOut=arro.retn();
11067   arrIndexOut=arrIo.retn();
11068 }
11069
11070 /*!
11071  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11072  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11073  *
11074  * \param [in] start begin of set of ids of the input extraction (included)
11075  * \param [in] end end of set of ids of the input extraction (excluded)
11076  * \param [in] step step of the set of ids in range mode.
11077  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11078  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11079  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11080  * \param [in] srcArrIndex index array of \b srcArr
11081  * 
11082  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11083  */
11084 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11085                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11086 {
11087   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11088     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11089   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11090   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11091   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11092   int *arrInOutPtr=arrInOut->getPointer();
11093   const int *srcArrPtr=srcArr->getConstPointer();
11094   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11095   int it=start;
11096   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11097     {
11098       if(it>=0 && it<nbOfTuples)
11099         {
11100           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11101             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11102           else
11103             {
11104               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11105               throw INTERP_KERNEL::Exception(oss.str().c_str());
11106             }
11107         }
11108       else
11109         {
11110           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11111           throw INTERP_KERNEL::Exception(oss.str().c_str());
11112         }
11113     }
11114 }
11115
11116 /*!
11117  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11118  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11119  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11120  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11121  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11122  * 
11123  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11124  */
11125 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11126 {
11127   checkFullyDefined();
11128   int mdim=getMeshDimension();
11129   int spaceDim=getSpaceDimension();
11130   if(mdim!=spaceDim)
11131     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11132   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11133   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11134   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11135   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11136   ret->setCoords(getCoords());
11137   ret->allocateCells((int)partition.size());
11138   //
11139   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11140     {
11141       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11142       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11143       switch(mdim)
11144       {
11145         case 2:
11146           cell=tmp->buildUnionOf2DMesh();
11147           break;
11148         case 3:
11149           cell=tmp->buildUnionOf3DMesh();
11150           break;
11151         default:
11152           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11153       }
11154
11155       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11156     }
11157   //
11158   ret->finishInsertingCells();
11159   return ret.retn();
11160 }
11161
11162 /*!
11163  * This method partitions \b this into contiguous zone.
11164  * This method only needs a well defined connectivity. Coordinates are not considered here.
11165  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11166  */
11167 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11168 {
11169   int nbOfCellsCur=getNumberOfCells();
11170   std::vector<DataArrayInt *> ret;
11171   if(nbOfCellsCur<=0)
11172     return ret;
11173   DataArrayInt *neigh=0,*neighI=0;
11174   computeNeighborsOfCells(neigh,neighI);
11175   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11176   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11177   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11178   int seed=0;
11179   while(seed<nbOfCellsCur)
11180     {
11181       int nbOfPeelPerformed=0;
11182       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11183       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11184     }
11185   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11186     ret.push_back((*it).retn());
11187   return ret;
11188 }
11189
11190 /*!
11191  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11192  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11193  *
11194  * \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.
11195  * \return a newly allocated DataArrayInt to be managed by the caller.
11196  * \throw In case of \a code has not the right format (typically of size 3*n)
11197  */
11198 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11199 {
11200   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11201   std::size_t nb=code.size()/3;
11202   if(code.size()%3!=0)
11203     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11204   ret->alloc((int)nb,2);
11205   int *retPtr=ret->getPointer();
11206   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11207     {
11208       retPtr[0]=code[3*i+2];
11209       retPtr[1]=code[3*i+2]+code[3*i+1];
11210     }
11211   return ret.retn();
11212 }
11213
11214 /*!
11215  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11216  * All cells in \a this are expected to be linear 3D cells.
11217  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11218  * It leads to an increase to number of cells.
11219  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11220  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11221  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11222  *
11223  * \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.
11224  *                      For all other cells, the splitting policy will be ignored.
11225  * \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. 
11226  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11227  *          an id of old cell producing it. The caller is to delete this array using
11228  *         decrRef() as it is no more needed.
11229  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11230  *
11231  * \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
11232  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11233  * 
11234  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11235  * \throw If \a this is not fully constituted with linear 3D cells.
11236  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11237  */
11238 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11239 {
11240   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11241   checkConnectivityFullyDefined();
11242   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11243     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11244   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11245   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11246   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11247   int *retPt(ret->getPointer());
11248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11249   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11250   const int *oldc(_nodal_connec->begin());
11251   const int *oldci(_nodal_connec_index->begin());
11252   const double *coords(_coords->begin());
11253   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11254     {
11255       std::vector<int> a; std::vector<double> b;
11256       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11257       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11258       const int *aa(&a[0]);
11259       if(!b.empty())
11260         {
11261           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11262             if(*it<0)
11263               *it=(-(*(it))-1+nbNodes);
11264           addPts->insertAtTheEnd(b.begin(),b.end());
11265           nbNodes+=(int)b.size()/3;
11266         }
11267       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11268         newConn->insertAtTheEnd(aa,aa+4);
11269     }
11270   if(!addPts->empty())
11271     {
11272       addPts->rearrange(3);
11273       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11274       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11275       ret0->setCoords(addPts);
11276     }
11277   else
11278     {
11279       nbOfAdditionalPoints=0;
11280       ret0->setCoords(getCoords());
11281     }
11282   ret0->setNodalConnectivity(newConn);
11283   //
11284   ret->computeOffsets2();
11285   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11286   return ret0.retn();
11287 }
11288
11289 /*!
11290  * 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). 
11291  *
11292  * \sa MEDCouplingUMesh::split2DCells
11293  */
11294 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11295 {
11296   checkConnectivityFullyDefined();
11297   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11299   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11300   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11301   int prevPosOfCi(ciPtr[0]);
11302   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11303     {
11304       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11305       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11306       for(int j=0;j<sz;j++)
11307         {
11308           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11309           for(int k=0;k<sz2;k++)
11310             *cPtr++=subPtr[offset2+k];
11311           if(j!=sz-1)
11312             *cPtr++=oldConn[prevPosOfCi+j+2];
11313           deltaSz+=sz2;
11314         }
11315       prevPosOfCi=ciPtr[1];
11316       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11317     }
11318   if(c->end()!=cPtr)
11319     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11320   _nodal_connec->decrRef();
11321   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11322 }
11323
11324 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11325 {
11326   if(id!=-1)
11327     return id;
11328   else
11329     {
11330       int ret(nodesCnter++);
11331       double newPt[2];
11332       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11333       addCoo.insertAtTheEnd(newPt,newPt+2);
11334       return ret;
11335     }
11336 }
11337
11338 /// @cond INTERNAL
11339
11340 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)
11341 {
11342   int tmp[3];
11343   int trueStart(start>=0?start:nbOfEdges+start);
11344   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11345   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11346   if(linOrArc)
11347     {
11348       if(stp-start>1)
11349         {
11350           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11351           InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11352           middles.push_back(tmp3+offset);
11353         }
11354       else
11355         middles.push_back(connBg[trueStart+nbOfEdges]);
11356     }
11357 }
11358
11359 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)
11360 {
11361   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11362   newConnOfCell->pushBackSilent(tmpEnd);
11363   if(linOrArc)
11364     {
11365       if(stp-start>1)
11366         {
11367           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11368           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11369           middles.push_back(tmp3+offset);
11370         }
11371       else
11372         middles.push_back(connBg[start+nbOfEdges]);
11373     }
11374 }
11375
11376 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)
11377 {
11378   if(linOrArc)
11379     {
11380       if(stp-start>1)
11381         {
11382           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11383           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11384           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11385           middles.push_back(tmp3+offset);
11386         }
11387       else
11388         middles.push_back(connBg[start+nbOfEdges]);
11389     }
11390 }
11391
11392 /// @cond INTERNAL
11393
11394 /*!
11395  * 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 ) .
11396  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11397  */
11398 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11399 {
11400   std::size_t sz(std::distance(connBg,connEnd));
11401   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11402     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11403   sz--;
11404   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11405   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11406   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
11407   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11408   INTERP_KERNEL::NormalizedCellType typeOfSon;
11409   std::vector<int> middles;
11410   bool ret(false);
11411   for(;nbOfHit<nbs;nbOfTurn++)
11412     {
11413       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11414       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11415       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11416       posEndElt++;
11417       nbOfHit++;
11418       unsigned endI(nbs-nbOfHit);
11419       for(unsigned i=0;i<endI;i++)
11420         {
11421           cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
11422           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11423           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11424           bool isColinear(eint->areColinears());
11425           if(isColinear)
11426             {
11427               nbOfHit++;
11428               posEndElt++;
11429               ret=true;
11430             }
11431           delete eint;
11432           eCand->decrRef();
11433           if(!isColinear)
11434             {
11435               if(nbOfTurn==0)
11436                 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
11437                   unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
11438                   for(unsigned ii=0;ii<endII;ii++)
11439                     {
11440                       cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
11441                       eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
11442                       eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
11443                       isColinear=eint->areColinears();
11444                       if(isColinear)
11445                         {
11446                           nbOfHit++;
11447                           posBaseElt--;
11448                           ret=true;
11449                         }
11450                       delete eint;
11451                       eCand->decrRef();
11452                       if(!isColinear)
11453                         break;
11454                     }
11455                 }
11456               break;
11457             }
11458         }
11459       //push [posBaseElt,posEndElt) in newConnOfCell using e
11460       if(nbOfTurn==0)
11461         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11462       else if(nbOfHit!=nbs)
11463         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11464       else
11465         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11466       posBaseElt=posEndElt;
11467       e->decrRef();
11468     }
11469   if(!middles.empty())
11470     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11471   return ret;
11472 }
11473
11474 /*!
11475  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11476  *
11477  * \return  int - the number of new nodes created.
11478  * \sa MEDCouplingUMesh::split2DCells
11479  */
11480 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11481 {
11482   checkCoherency();
11483   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11484   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11485   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11486   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11487   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11488   const double *oldCoordsPtr(getCoords()->begin());
11489   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11490   int prevPosOfCi(ciPtr[0]);
11491   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11492     {
11493       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11494       for(int j=0;j<sz;j++)
11495         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11496       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11497       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11498         {
11499           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11500           if(sz2==0)
11501             {
11502               if(j<sz-1)
11503                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11504               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11505               continue;
11506             }
11507           std::vector<INTERP_KERNEL::Node *> ns(3);
11508           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11509           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11510           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11511           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11512           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11513             {
11514               cPtr[1]=subPtr[offset2+k];
11515               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11516             }
11517           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11518           if(j!=sz-1)
11519             { cPtr[1]=tmpEnd; }
11520           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11521         }
11522       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11523       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11524     }
11525   if(c->end()!=cPtr)
11526     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11527   _nodal_connec->decrRef();
11528   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11529   addCoo->rearrange(2);
11530   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11531   setCoords(coo);
11532   return addCoo->getNumberOfTuples();
11533 }
11534
11535 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11536     _own_cell(true),_cell_id(-1),_nb_cell(0)
11537 {
11538   if(mesh)
11539     {
11540       mesh->incrRef();
11541       _nb_cell=mesh->getNumberOfCells();
11542     }
11543 }
11544
11545 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11546 {
11547   if(_mesh)
11548     _mesh->decrRef();
11549   if(_own_cell)
11550     delete _cell;
11551 }
11552
11553 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11554     _own_cell(false),_cell_id(bg-1),
11555     _nb_cell(end)
11556 {
11557   if(mesh)
11558     mesh->incrRef();
11559 }
11560
11561 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11562 {
11563   _cell_id++;
11564   if(_cell_id<_nb_cell)
11565     {
11566       _cell->next();
11567       return _cell;
11568     }
11569   else
11570     return 0;
11571 }
11572
11573 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11574 {
11575   if(_mesh)
11576     _mesh->incrRef();
11577 }
11578
11579 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11580 {
11581   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11582 }
11583
11584 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11585 {
11586   if(_mesh)
11587     _mesh->decrRef();
11588 }
11589
11590 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11591     _itc(itc),
11592     _bg(bg),_end(end)
11593 {
11594   if(_mesh)
11595     _mesh->incrRef();
11596 }
11597
11598 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11599 {
11600   if(_mesh)
11601     _mesh->decrRef();
11602 }
11603
11604 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11605 {
11606   return _type;
11607 }
11608
11609 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11610 {
11611   return _end-_bg;
11612 }
11613
11614 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11615 {
11616   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11617 }
11618
11619 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11620 {
11621   if(mesh)
11622     {
11623       mesh->incrRef();
11624       _nb_cell=mesh->getNumberOfCells();
11625     }
11626 }
11627
11628 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11629 {
11630   if(_mesh)
11631     _mesh->decrRef();
11632   delete _cell;
11633 }
11634
11635 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11636 {
11637   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11638   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11639   if(_cell_id<_nb_cell)
11640     {
11641       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11642       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11643       int startId=_cell_id;
11644       _cell_id+=nbOfElems;
11645       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11646     }
11647   else
11648     return 0;
11649 }
11650
11651 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11652 {
11653   if(mesh)
11654     {
11655       _conn=mesh->getNodalConnectivity()->getPointer();
11656       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11657     }
11658 }
11659
11660 void MEDCouplingUMeshCell::next()
11661 {
11662   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11663     {
11664       _conn+=_conn_lgth;
11665       _conn_indx++;
11666     }
11667   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11668 }
11669
11670 std::string MEDCouplingUMeshCell::repr() const
11671 {
11672   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11673     {
11674       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11675       oss << " : ";
11676       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11677       return oss.str();
11678     }
11679   else
11680     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11681 }
11682
11683 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11684 {
11685   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11686     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11687   else
11688     return INTERP_KERNEL::NORM_ERROR;
11689 }
11690
11691 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11692 {
11693   lgth=_conn_lgth;
11694   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11695     return _conn;
11696   else
11697     return 0;
11698 }