Salome HOME
Merge branch 'master' into V7_5_BR
[modules/med.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 /*!
93  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94  * The coordinates are shared between \a this and the returned instance.
95  * 
96  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97  * \sa MEDCouplingUMesh::deepCpy
98  */
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
100 {
101   checkConnectivityFullyDefined();
102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104   ret->setConnectivity(c,ci);
105   return ret.retn();
106 }
107
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
109 {
110   if(!other)
111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
113   if(!otherC)
114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
117 }
118
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
120 {
121   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
122   return ret;
123 }
124
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
126 {
127   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
128   ret.push_back(_nodal_connec);
129   ret.push_back(_nodal_connec_index);
130   return ret;
131 }
132
133 void MEDCouplingUMesh::updateTime() const
134 {
135   MEDCouplingPointSet::updateTime();
136   if(_nodal_connec)
137     {
138       updateTimeWith(*_nodal_connec);
139     }
140   if(_nodal_connec_index)
141     {
142       updateTimeWith(*_nodal_connec_index);
143     }
144 }
145
146 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
147 {
148 }
149
150 /*!
151  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
152  * then \a this mesh is most probably is writable, exchangeable and available for most
153  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
154  * this method to check that all is in order with \a this mesh.
155  *  \throw If the mesh dimension is not set.
156  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
157  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
158  *  \throw If the connectivity data array has more than one component.
159  *  \throw If the connectivity data array has a named component.
160  *  \throw If the connectivity index data array has more than one component.
161  *  \throw If the connectivity index data array has a named component.
162  */
163 void MEDCouplingUMesh::checkCoherency() const
164 {
165   if(_mesh_dim<-1)
166     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
167   if(_mesh_dim!=-1)
168     MEDCouplingPointSet::checkCoherency();
169   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
170     {
171       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
172         {
173           std::ostringstream message;
174           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
175           throw INTERP_KERNEL::Exception(message.str().c_str());
176         }
177     }
178   if(_nodal_connec)
179     {
180       if(_nodal_connec->getNumberOfComponents()!=1)
181         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
182       if(_nodal_connec->getInfoOnComponent(0)!="")
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
184     }
185   else
186     if(_mesh_dim!=-1)
187       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
188   if(_nodal_connec_index)
189     {
190       if(_nodal_connec_index->getNumberOfComponents()!=1)
191         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
192       if(_nodal_connec_index->getInfoOnComponent(0)!="")
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
194     }
195   else
196     if(_mesh_dim!=-1)
197       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
198 }
199
200 /*!
201  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
202  * then \a this mesh is most probably is writable, exchangeable and available for all
203  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
204  * method thoroughly checks the nodal connectivity.
205  *  \param [in] eps - a not used parameter.
206  *  \throw If the mesh dimension is not set.
207  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
208  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
209  *  \throw If the connectivity data array has more than one component.
210  *  \throw If the connectivity data array has a named component.
211  *  \throw If the connectivity index data array has more than one component.
212  *  \throw If the connectivity index data array has a named component.
213  *  \throw If number of nodes defining an element does not correspond to the type of element.
214  *  \throw If the nodal connectivity includes an invalid node id.
215  */
216 void MEDCouplingUMesh::checkCoherency1(double eps) const
217 {
218   checkCoherency();
219   if(_mesh_dim==-1)
220     return ;
221   int meshDim=getMeshDimension();
222   int nbOfNodes=getNumberOfNodes();
223   int nbOfCells=getNumberOfCells();
224   const int *ptr=_nodal_connec->getConstPointer();
225   const int *ptrI=_nodal_connec_index->getConstPointer();
226   for(int i=0;i<nbOfCells;i++)
227     {
228       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
229       if((int)cm.getDimension()!=meshDim)
230         {
231           std::ostringstream oss;
232           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
233           throw INTERP_KERNEL::Exception(oss.str().c_str());
234         }
235       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
236       if(!cm.isDynamic())
237         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
238           {
239             std::ostringstream oss;
240             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
241             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
242             throw INTERP_KERNEL::Exception(oss.str().c_str());
243           }
244       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
245         {
246           int nodeId=*w;
247           if(nodeId>=0)
248             {
249               if(nodeId>=nbOfNodes)
250                 {
251                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
252                   throw INTERP_KERNEL::Exception(oss.str().c_str());
253                 }
254             }
255           else if(nodeId<-1)
256             {
257               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
258               throw INTERP_KERNEL::Exception(oss.str().c_str());
259             }
260           else
261             {
262               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
263                 {
264                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
265                   throw INTERP_KERNEL::Exception(oss.str().c_str());
266                 }
267             }
268         }
269     }
270 }
271
272
273 /*!
274  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
275  * then \a this mesh is most probably is writable, exchangeable and available for all
276  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
277  *  \param [in] eps - a not used parameter.
278  *  \throw If the mesh dimension is not set.
279  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
280  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
281  *  \throw If the connectivity data array has more than one component.
282  *  \throw If the connectivity data array has a named component.
283  *  \throw If the connectivity index data array has more than one component.
284  *  \throw If the connectivity index data array has a named component.
285  *  \throw If number of nodes defining an element does not correspond to the type of element.
286  *  \throw If the nodal connectivity includes an invalid node id.
287  */
288 void MEDCouplingUMesh::checkCoherency2(double eps) const
289 {
290   checkCoherency1(eps);
291 }
292
293 /*!
294  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
295  * elements contained in the mesh. For more info on the mesh dimension see
296  * \ref MEDCouplingUMeshPage.
297  *  \param [in] meshDim - a new mesh dimension.
298  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
299  */
300 void MEDCouplingUMesh::setMeshDimension(int meshDim)
301 {
302   if(meshDim<-1 || meshDim>3)
303     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
304   _mesh_dim=meshDim;
305   declareAsNew();
306 }
307
308 /*!
309  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
310  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
311  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
312  *
313  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
314  *
315  *  \if ENABLE_EXAMPLES
316  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
317  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
318  *  \endif
319  */
320 void MEDCouplingUMesh::allocateCells(int nbOfCells)
321 {
322   if(nbOfCells<0)
323     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
324   if(_nodal_connec_index)
325     {
326       _nodal_connec_index->decrRef();
327     }
328   if(_nodal_connec)
329     {
330       _nodal_connec->decrRef();
331     }
332   _nodal_connec_index=DataArrayInt::New();
333   _nodal_connec_index->reserve(nbOfCells+1);
334   _nodal_connec_index->pushBackSilent(0);
335   _nodal_connec=DataArrayInt::New();
336   _nodal_connec->reserve(2*nbOfCells);
337   _types.clear();
338   declareAsNew();
339 }
340
341 /*!
342  * Appends a cell to the connectivity array. For deeper understanding what is
343  * happening see \ref MEDCouplingUMeshNodalConnectivity.
344  *  \param [in] type - type of cell to add.
345  *  \param [in] size - number of nodes constituting this cell.
346  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
347  * 
348  *  \if ENABLE_EXAMPLES
349  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
350  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
351  *  \endif
352  */
353 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
354 {
355   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
356   if(_nodal_connec_index==0)
357     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
358   if((int)cm.getDimension()==_mesh_dim)
359     {
360       if(!cm.isDynamic())
361         if(size!=(int)cm.getNumberOfNodes())
362           {
363             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
364             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
365             throw INTERP_KERNEL::Exception(oss.str().c_str());
366           }
367       int idx=_nodal_connec_index->back();
368       int val=idx+size+1;
369       _nodal_connec_index->pushBackSilent(val);
370       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
371       _types.insert(type);
372     }
373   else
374     {
375       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
376       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
377       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
378       throw INTERP_KERNEL::Exception(oss.str().c_str());
379     }
380 }
381
382 /*!
383  * Compacts data arrays to release unused memory. This method is to be called after
384  * finishing cell insertion using \a this->insertNextCell().
385  * 
386  *  \if ENABLE_EXAMPLES
387  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
388  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
389  *  \endif
390  */
391 void MEDCouplingUMesh::finishInsertingCells()
392 {
393   _nodal_connec->pack();
394   _nodal_connec_index->pack();
395   _nodal_connec->declareAsNew();
396   _nodal_connec_index->declareAsNew();
397   updateTime();
398 }
399
400 /*!
401  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
402  * Useful for python users.
403  */
404 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
405 {
406   return new MEDCouplingUMeshCellIterator(this);
407 }
408
409 /*!
410  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
411  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
412  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
413  * Useful for python users.
414  */
415 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
416 {
417   if(!checkConsecutiveCellTypes())
418     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
419   return new MEDCouplingUMeshCellByTypeEntry(this);
420 }
421
422 /*!
423  * Returns a set of all cell types available in \a this mesh.
424  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
425  * \warning this method does not throw any exception even if \a this is not defined.
426  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
427  */
428 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
429 {
430   return _types;
431 }
432
433 /*!
434  * This method returns the sorted list of geometric types in \a this.
435  * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
436  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
437  *
438  * \throw if connectivity in \a this is not correctly defined.
439  *  
440  * \sa MEDCouplingMesh::getAllGeoTypes
441  */
442 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
443 {
444   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
445   checkConnectivityFullyDefined();
446   int nbOfCells(getNumberOfCells());
447   if(nbOfCells==0)
448     return ret;
449   if(getMeshLength()<1)
450     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
451   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
452   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
453   for(int i=1;i<nbOfCells;i++,ci++)
454     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
455       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
456   return ret;
457 }
458
459 /*!
460  * This method is a method that compares \a this and \a other.
461  * This method compares \b all attributes, even names and component names.
462  */
463 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
464 {
465   if(!other)
466     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
467   std::ostringstream oss; oss.precision(15);
468   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
469   if(!otherC)
470     {
471       reason="mesh given in input is not castable in MEDCouplingUMesh !";
472       return false;
473     }
474   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
475     return false;
476   if(_mesh_dim!=otherC->_mesh_dim)
477     {
478       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
479       reason=oss.str();
480       return false;
481     }
482   if(_types!=otherC->_types)
483     {
484       oss << "umesh geometric type mismatch :\nThis geometric types are :";
485       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
486         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
487       oss << "\nOther geometric types are :";
488       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
489         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
490       reason=oss.str();
491       return false;
492     }
493   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
494     if(_nodal_connec==0 || otherC->_nodal_connec==0)
495       {
496         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
497         return false;
498       }
499   if(_nodal_connec!=otherC->_nodal_connec)
500     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
501       {
502         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
503         return false;
504       }
505   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
506     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
507       {
508         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
509         return false;
510       }
511   if(_nodal_connec_index!=otherC->_nodal_connec_index)
512     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
513       {
514         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
515         return false;
516       }
517   return true;
518 }
519
520 /*!
521  * Checks if data arrays of this mesh (node coordinates, nodal
522  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
523  * not considered.
524  *  \param [in] other - the mesh to compare with.
525  *  \param [in] prec - precision value used to compare node coordinates.
526  *  \return bool - \a true if the two meshes are same.
527  */
528 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
529 {
530   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
531   if(!otherC)
532     return false;
533   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
534     return false;
535   if(_mesh_dim!=otherC->_mesh_dim)
536     return false;
537   if(_types!=otherC->_types)
538     return false;
539   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
540     if(_nodal_connec==0 || otherC->_nodal_connec==0)
541       return false;
542   if(_nodal_connec!=otherC->_nodal_connec)
543     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
544       return false;
545   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
546     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
547       return false;
548   if(_nodal_connec_index!=otherC->_nodal_connec_index)
549     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
550       return false;
551   return true;
552 }
553
554 /*!
555  * Checks if \a this and \a other meshes are geometrically equivalent with high
556  * probability, else an exception is thrown. The meshes are considered equivalent if
557  * (1) meshes contain the same number of nodes and the same number of elements of the
558  * same types (2) three cells of the two meshes (first, last and middle) are based
559  * on coincident nodes (with a specified precision).
560  *  \param [in] other - the mesh to compare with.
561  *  \param [in] prec - the precision used to compare nodes of the two meshes.
562  *  \throw If the two meshes do not match.
563  */
564 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
565 {
566   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
567   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
568   if(!otherC)
569     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
570 }
571
572 /*!
573  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
574  * cells each node belongs to.
575  * \warning For speed reasons, this method does not check if node ids in the nodal
576  *          connectivity correspond to the size of node coordinates array.
577  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
578  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
579  *        dividing cell ids in \a revNodal into groups each referring to one
580  *        node. Its every element (except the last one) is an index pointing to the
581  *         first id of a group of cells. For example cells sharing the node #1 are 
582  *        described by following range of indices: 
583  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
584  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
585  *        Number of cells sharing the *i*-th node is
586  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
587  * \throw If the coordinates array is not set.
588  * \throw If the nodal connectivity of cells is not defined.
589  * 
590  * \if ENABLE_EXAMPLES
591  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
592  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
593  * \endif
594  */
595 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
596 {
597   checkFullyDefined();
598   int nbOfNodes=getNumberOfNodes();
599   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
600   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
601   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
602   const int *conn=_nodal_connec->getConstPointer();
603   const int *connIndex=_nodal_connec_index->getConstPointer();
604   int nbOfCells=getNumberOfCells();
605   int nbOfEltsInRevNodal=0;
606   for(int eltId=0;eltId<nbOfCells;eltId++)
607     {
608       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
609       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
610       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
611         if(*iter>=0)//for polyhedrons
612           {
613             nbOfEltsInRevNodal++;
614             revNodalIndxPtr[(*iter)+1]++;
615           }
616     }
617   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
618   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
619   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
620   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
621   for(int eltId=0;eltId<nbOfCells;eltId++)
622     {
623       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
624       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
625       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
626         if(*iter>=0)//for polyhedrons
627           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
628     }
629 }
630
631 /// @cond INTERNAL
632
633 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
634 {
635   return id;
636 }
637
638 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
639 {
640   if(!compute)
641     return id+1;
642   else
643     {
644       if(cm.getOrientationStatus(nb,conn1,conn2))
645         return id+1;
646       else
647         return -(id+1);
648     }
649 }
650
651 class MinusOneSonsGenerator
652 {
653 public:
654   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
655   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
656   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
657   static const int DELTA=1;
658 private:
659   const INTERP_KERNEL::CellModel& _cm;
660 };
661
662 class MinusOneSonsGeneratorBiQuadratic
663 {
664 public:
665   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
666   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
667   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
668   static const int DELTA=1;
669 private:
670   const INTERP_KERNEL::CellModel& _cm;
671 };
672
673 class MinusTwoSonsGenerator
674 {
675 public:
676   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
677   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
678   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
679   static const int DELTA=2;
680 private:
681   const INTERP_KERNEL::CellModel& _cm;
682 };
683
684 /// @endcond
685
686 /*!
687  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
688  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
689  * describing correspondence between cells of \a this and the result meshes are
690  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
691  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
692  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
693  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
694  * \warning For speed reasons, this method does not check if node ids in the nodal
695  *          connectivity correspond to the size of node coordinates array.
696  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
697  *          to write this mesh to the MED file, its cells must be sorted using
698  *          sortCellsInMEDFileFrmt().
699  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
700  *         each cell of \a this mesh.
701  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
702  *        dividing cell ids in \a desc into groups each referring to one
703  *        cell of \a this mesh. Its every element (except the last one) is an index
704  *        pointing to the first id of a group of cells. For example cells of the
705  *        result mesh bounding the cell #1 of \a this mesh are described by following
706  *        range of indices:
707  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
708  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
709  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
710  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
711  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
712  *         by each cell of the result mesh.
713  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
714  *        in the result mesh,
715  *        dividing cell ids in \a revDesc into groups each referring to one
716  *        cell of the result mesh the same way as \a descIndx divides \a desc.
717  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
718  *        delete this mesh using decrRef() as it is no more needed.
719  *  \throw If the coordinates array is not set.
720  *  \throw If the nodal connectivity of cells is node defined.
721  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
722  *         revDescIndx == NULL.
723  * 
724  *  \if ENABLE_EXAMPLES
725  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
726  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
727  *  \endif
728  * \sa buildDescendingConnectivity2()
729  */
730 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
731 {
732   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
733 }
734
735 /*!
736  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
737  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
738  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
739  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
740  * \sa MEDCouplingUMesh::buildDescendingConnectivity
741  */
742 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
743 {
744   checkFullyDefined();
745   if(getMeshDimension()!=3)
746     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
747   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
748 }
749
750 /*!
751  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
752  * this->getMeshDimension(), that bound cells of \a this mesh. In
753  * addition arrays describing correspondence between cells of \a this and the result
754  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
755  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
756  *  mesh. This method differs from buildDescendingConnectivity() in that apart
757  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
758  * result meshes. So a positive id means that order of nodes in corresponding cells
759  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
760  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
761  * i.e. cell ids are one-based.
762  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
763  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
764  * \warning For speed reasons, this method does not check if node ids in the nodal
765  *          connectivity correspond to the size of node coordinates array.
766  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
767  *          to write this mesh to the MED file, its cells must be sorted using
768  *          sortCellsInMEDFileFrmt().
769  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
770  *         each cell of \a this mesh.
771  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
772  *        dividing cell ids in \a desc into groups each referring to one
773  *        cell of \a this mesh. Its every element (except the last one) is an index
774  *        pointing to the first id of a group of cells. For example cells of the
775  *        result mesh bounding the cell #1 of \a this mesh are described by following
776  *        range of indices:
777  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
778  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
779  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
780  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
781  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
782  *         by each cell of the result mesh.
783  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
784  *        in the result mesh,
785  *        dividing cell ids in \a revDesc into groups each referring to one
786  *        cell of the result mesh the same way as \a descIndx divides \a desc.
787  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
788  *        shares the node coordinates array with \a this mesh. The caller is to
789  *        delete this mesh using decrRef() as it is no more needed.
790  *  \throw If the coordinates array is not set.
791  *  \throw If the nodal connectivity of cells is node defined.
792  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
793  *         revDescIndx == NULL.
794  * 
795  *  \if ENABLE_EXAMPLES
796  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
797  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
798  *  \endif
799  * \sa buildDescendingConnectivity()
800  */
801 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
802 {
803   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
804 }
805
806 /*!
807  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
808  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
809  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
810  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
811  *
812  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
813  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
814  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
815  */
816 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
817 {
818   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
819   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
822   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
823   meshDM1=0;
824   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
825 }
826
827 /*!
828  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
829  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
830  * excluding a set of meshdim-1 cells in input descending connectivity.
831  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
832  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
833  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
834  *
835  * \param [in] desc descending connectivity array.
836  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
837  * \param [in] revDesc reverse descending connectivity array.
838  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
839  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
840  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
841  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
842  */
843 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
844                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
845 {
846   if(!desc || !descIndx || !revDesc || !revDescIndx)
847     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
848   const int *descPtr=desc->getConstPointer();
849   const int *descIPtr=descIndx->getConstPointer();
850   const int *revDescPtr=revDesc->getConstPointer();
851   const int *revDescIPtr=revDescIndx->getConstPointer();
852   //
853   int nbCells=descIndx->getNumberOfTuples()-1;
854   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
855   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
856   int *out1Ptr=out1->getPointer();
857   *out1Ptr++=0;
858   out0->reserve(desc->getNumberOfTuples());
859   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
860     {
861       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
862         {
863           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
864           s.erase(i);
865           out0->insertAtTheEnd(s.begin(),s.end());
866         }
867       *out1Ptr=out0->getNumberOfTuples();
868     }
869   neighbors=out0.retn();
870   neighborsIndx=out1.retn();
871 }
872
873 /*!
874  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
875  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
876  * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
877  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
878  *
879  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
880  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
881  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
882  */
883 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
884 {
885   checkFullyDefined();
886   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
888   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
889   switch(mdim)
890   {
891     case 3:
892       {
893         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
894         break;
895       }
896     case 2:
897       {
898         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
899         break;
900       }
901     case 1:
902       {
903         mesh1D=const_cast<MEDCouplingUMesh *>(this);
904         mesh1D->incrRef();
905         break;
906       }
907     default:
908       {
909         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
910       }
911   }
912   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
913   mesh1D->getReverseNodalConnectivity(desc,descIndx);
914   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
915   ret0->alloc(desc->getNumberOfTuples(),1);
916   int *r0Pt(ret0->getPointer());
917   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
918   for(int i=0;i<nbNodes;i++,rni++)
919     {
920       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
921         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
922     }
923   neighbors=ret0.retn();
924   neighborsIdx=descIndx.retn();
925 }
926
927 /// @cond INTERNAL
928
929 /*!
930  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
931  * For speed reasons no check of this will be done.
932  */
933 template<class SonsGenerator>
934 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
935 {
936   if(!desc || !descIndx || !revDesc || !revDescIndx)
937     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
938   checkConnectivityFullyDefined();
939   int nbOfCells=getNumberOfCells();
940   int nbOfNodes=getNumberOfNodes();
941   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
942   int *revNodalIndxPtr=revNodalIndx->getPointer();
943   const int *conn=_nodal_connec->getConstPointer();
944   const int *connIndex=_nodal_connec_index->getConstPointer();
945   std::string name="Mesh constituent of "; name+=getName();
946   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
947   ret->setCoords(getCoords());
948   ret->allocateCells(2*nbOfCells);
949   descIndx->alloc(nbOfCells+1,1);
950   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
951   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
952   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
953     {
954       int pos=connIndex[eltId];
955       int posP1=connIndex[eltId+1];
956       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
957       SonsGenerator sg(cm);
958       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
959       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
960       for(unsigned i=0;i<nbOfSons;i++)
961         {
962           INTERP_KERNEL::NormalizedCellType cmsId;
963           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
964           for(unsigned k=0;k<nbOfNodesSon;k++)
965             if(tmp[k]>=0)
966               revNodalIndxPtr[tmp[k]+1]++;
967           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
968           revDesc2->pushBackSilent(eltId);
969         }
970       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
971     }
972   int nbOfCellsM1=ret->getNumberOfCells();
973   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
975   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
976   int *revNodalPtr=revNodal->getPointer();
977   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
978   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
979   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
980     {
981       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
982       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
983       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
984         if(*iter>=0)//for polyhedrons
985           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
986     }
987   //
988   DataArrayInt *commonCells=0,*commonCellsI=0;
989   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
990   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
991   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
992   int newNbOfCellsM1=-1;
993   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
994                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
995   std::vector<bool> isImpacted(nbOfCellsM1,false);
996   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
997     for(int work2=work[0];work2!=work[1];work2++)
998       isImpacted[commonCellsPtr[work2]]=true;
999   const int *o2nM1Ptr=o2nM1->getConstPointer();
1000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1001   const int *n2oM1Ptr=n2oM1->getConstPointer();
1002   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1003   ret2->copyTinyInfoFrom(this);
1004   desc->alloc(descIndx->back(),1);
1005   int *descPtr=desc->getPointer();
1006   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1007   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1008     {
1009       if(!isImpacted[i])
1010         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1011       else
1012         {
1013           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1014             {
1015               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1016               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1017             }
1018           else
1019             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1020         }
1021     }
1022   revDesc->reserve(newNbOfCellsM1);
1023   revDescIndx->alloc(newNbOfCellsM1+1,1);
1024   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1025   const int *revDesc2Ptr=revDesc2->getConstPointer();
1026   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1027     {
1028       int oldCellIdM1=n2oM1Ptr[i];
1029       if(!isImpacted[oldCellIdM1])
1030         {
1031           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1032           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1033         }
1034       else
1035         {
1036           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1037             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1038           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1039           commonCellsIPtr++;
1040         }
1041     }
1042   //
1043   return ret2.retn();
1044 }
1045
1046 struct MEDCouplingAccVisit
1047 {
1048   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1049   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1050   int _new_nb_of_nodes;
1051 };
1052
1053 /// @endcond
1054
1055 /*!
1056  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1057  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1058  * array of cell ids. Pay attention that after conversion all algorithms work slower
1059  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1060  * conversion due presence of invalid ids in the array of cells to convert, as a
1061  * result \a this mesh contains some already converted elements. In this case the 2D
1062  * mesh remains valid but 3D mesh becomes \b inconsistent!
1063  *  \warning This method can significantly modify the order of geometric types in \a this,
1064  *          hence, to write this mesh to the MED file, its cells must be sorted using
1065  *          sortCellsInMEDFileFrmt().
1066  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1067  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1068  *         cellIdsToConvertBg.
1069  *  \throw If the coordinates array is not set.
1070  *  \throw If the nodal connectivity of cells is node defined.
1071  *  \throw If dimension of \a this mesh is not either 2 or 3.
1072  *
1073  *  \if ENABLE_EXAMPLES
1074  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1075  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1076  *  \endif
1077  */
1078 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1079 {
1080   checkFullyDefined();
1081   int dim=getMeshDimension();
1082   if(dim<2 || dim>3)
1083     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1084   int nbOfCells(getNumberOfCells());
1085   if(dim==2)
1086     {
1087       const int *connIndex=_nodal_connec_index->getConstPointer();
1088       int *conn=_nodal_connec->getPointer();
1089       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1090         {
1091           if(*iter>=0 && *iter<nbOfCells)
1092             {
1093               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1094               if(!cm.isQuadratic())
1095                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1096               else
1097                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1098             }
1099           else
1100             {
1101               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1102               oss << " in range [0," << nbOfCells << ") !";
1103               throw INTERP_KERNEL::Exception(oss.str().c_str());
1104             }
1105         }
1106     }
1107   else
1108     {
1109       int *connIndex(_nodal_connec_index->getPointer());
1110       const int *connOld(_nodal_connec->getConstPointer());
1111       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1112       std::vector<bool> toBeDone(nbOfCells,false);
1113       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1114         {
1115           if(*iter>=0 && *iter<nbOfCells)
1116             toBeDone[*iter]=true;
1117           else
1118             {
1119               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1120               oss << " in range [0," << nbOfCells << ") !";
1121               throw INTERP_KERNEL::Exception(oss.str().c_str());
1122             }
1123         }
1124       for(int cellId=0;cellId<nbOfCells;cellId++)
1125         {
1126           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1127           int lgthOld(posP1-pos-1);
1128           if(toBeDone[cellId])
1129             {
1130               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1131               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1132               int *tmp(new int[nbOfFaces*lgthOld+1]);
1133               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1134               for(unsigned j=0;j<nbOfFaces;j++)
1135                 {
1136                   INTERP_KERNEL::NormalizedCellType type;
1137                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1138                   work+=offset;
1139                   *work++=-1;
1140                 }
1141               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1142               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1143               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1144               delete [] tmp;
1145             }
1146           else
1147             {
1148               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1149               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1150             }
1151         }
1152       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1153     }
1154   computeTypes();
1155 }
1156
1157 /*!
1158  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1159  * polyhedrons (if \a this is a 3D mesh).
1160  *  \warning As this method is purely for user-friendliness and no optimization is
1161  *          done to avoid construction of a useless vector, this method can be costly
1162  *          in memory.
1163  *  \throw If the coordinates array is not set.
1164  *  \throw If the nodal connectivity of cells is node defined.
1165  *  \throw If dimension of \a this mesh is not either 2 or 3.
1166  */
1167 void MEDCouplingUMesh::convertAllToPoly()
1168 {
1169   int nbOfCells=getNumberOfCells();
1170   std::vector<int> cellIds(nbOfCells);
1171   for(int i=0;i<nbOfCells;i++)
1172     cellIds[i]=i;
1173   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1174 }
1175
1176 /*!
1177  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1178  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1179  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1180  * base facet of the volume and the second half of nodes describes an opposite facet
1181  * having the same number of nodes as the base one. This method converts such
1182  * connectivity to a valid polyhedral format where connectivity of each facet is
1183  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1184  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1185  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1186  * a correct orientation of the first facet of a polyhedron, else orientation of a
1187  * corrected cell is reverse.<br>
1188  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1189  * it releases the user from boring description of polyhedra connectivity in the valid
1190  * format.
1191  *  \throw If \a this->getMeshDimension() != 3.
1192  *  \throw If \a this->getSpaceDimension() != 3.
1193  *  \throw If the nodal connectivity of cells is not defined.
1194  *  \throw If the coordinates array is not set.
1195  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1196  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1197  *
1198  *  \if ENABLE_EXAMPLES
1199  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1200  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1201  *  \endif
1202  */
1203 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1204 {
1205   checkFullyDefined();
1206   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1207     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1208   int nbOfCells=getNumberOfCells();
1209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1210   newCi->alloc(nbOfCells+1,1);
1211   int *newci=newCi->getPointer();
1212   const int *ci=_nodal_connec_index->getConstPointer();
1213   const int *c=_nodal_connec->getConstPointer();
1214   newci[0]=0;
1215   for(int i=0;i<nbOfCells;i++)
1216     {
1217       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1218       if(type==INTERP_KERNEL::NORM_POLYHED)
1219         {
1220           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1221             {
1222               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1223               throw INTERP_KERNEL::Exception(oss.str().c_str());
1224             }
1225           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1226           if(n2%2!=0)
1227             {
1228               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron with 1 face but there is a mismatch of number of nodes in face should be even !";
1229               throw INTERP_KERNEL::Exception(oss.str().c_str());
1230             }
1231           int n1=(int)(n2/2);
1232           newci[i+1]=7*n1+2+newci[i];//6*n1 (nodal length) + n1+2 (number of faces) - 1 (number of '-1' separator is equal to number of faces -1) + 1 (for cell type)
1233         }
1234       else
1235         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1236     }
1237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1238   newC->alloc(newci[nbOfCells],1);
1239   int *newc=newC->getPointer();
1240   for(int i=0;i<nbOfCells;i++)
1241     {
1242       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1243       if(type==INTERP_KERNEL::NORM_POLYHED)
1244         {
1245           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1246           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1247           *newc++=-1;
1248           for(std::size_t j=0;j<n1;j++)
1249             {
1250               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1251               newc[n1+5*j]=-1;
1252               newc[n1+5*j+1]=c[ci[i]+1+j];
1253               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1254               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1255               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1256             }
1257           newc+=n1*6;
1258         }
1259       else
1260         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1261     }
1262   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1263   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1264 }
1265
1266
1267 /*!
1268  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1269  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1270  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1271  *          to write this mesh to the MED file, its cells must be sorted using
1272  *          sortCellsInMEDFileFrmt().
1273  * \return \c true if at least one cell has been converted, \c false else. In the
1274  *         last case the nodal connectivity remains unchanged.
1275  * \throw If the coordinates array is not set.
1276  * \throw If the nodal connectivity of cells is not defined.
1277  * \throw If \a this->getMeshDimension() < 0.
1278  */
1279 bool MEDCouplingUMesh::unPolyze()
1280 {
1281   checkFullyDefined();
1282   int mdim=getMeshDimension();
1283   if(mdim<0)
1284     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1285   if(mdim<=1)
1286     return false;
1287   int nbOfCells=getNumberOfCells();
1288   if(nbOfCells<1)
1289     return false;
1290   int initMeshLgth=getMeshLength();
1291   int *conn=_nodal_connec->getPointer();
1292   int *index=_nodal_connec_index->getPointer();
1293   int posOfCurCell=0;
1294   int newPos=0;
1295   int lgthOfCurCell;
1296   bool ret=false;
1297   for(int i=0;i<nbOfCells;i++)
1298     {
1299       lgthOfCurCell=index[i+1]-posOfCurCell;
1300       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1301       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1302       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1303       int newLgth;
1304       if(cm.isDynamic())
1305         {
1306           switch(cm.getDimension())
1307           {
1308             case 2:
1309               {
1310                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1311                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1312                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1313                 break;
1314               }
1315             case 3:
1316               {
1317                 int nbOfFaces,lgthOfPolyhConn;
1318                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1319                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1320                 break;
1321               }
1322             case 1:
1323               {
1324                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1325                 break;
1326               }
1327           }
1328           ret=ret || (newType!=type);
1329           conn[newPos]=newType;
1330           newPos+=newLgth+1;
1331           posOfCurCell=index[i+1];
1332           index[i+1]=newPos;
1333         }
1334       else
1335         {
1336           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1337           newPos+=lgthOfCurCell;
1338           posOfCurCell+=lgthOfCurCell;
1339           index[i+1]=newPos;
1340         }
1341     }
1342   if(newPos!=initMeshLgth)
1343     _nodal_connec->reAlloc(newPos);
1344   if(ret)
1345     computeTypes();
1346   return ret;
1347 }
1348
1349 /*!
1350  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1351  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1352  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1353  *
1354  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not. This epsilon is used to recenter around origin to have maximal 
1355  *             precision.
1356  */
1357 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1358 {
1359   checkFullyDefined();
1360   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1361     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1362   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1363   coords->recenterForMaxPrecision(eps);
1364   //
1365   int nbOfCells=getNumberOfCells();
1366   const int *conn=_nodal_connec->getConstPointer();
1367   const int *index=_nodal_connec_index->getConstPointer();
1368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1369   connINew->alloc(nbOfCells+1,1);
1370   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1371   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1372   bool changed=false;
1373   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1374     {
1375       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1376         {
1377           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1378           changed=true;
1379         }
1380       else
1381         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1382       *connINewPtr=connNew->getNumberOfTuples();
1383     }
1384   if(changed)
1385     setConnectivity(connNew,connINew,false);
1386 }
1387
1388 /*!
1389  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1390  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1391  * the format of returned DataArrayInt instance.
1392  * 
1393  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1394  * \sa MEDCouplingUMesh::getNodeIdsInUse
1395  */
1396 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1397 {
1398   checkConnectivityFullyDefined();
1399   int nbOfCells=getNumberOfCells();
1400   const int *connIndex=_nodal_connec_index->getConstPointer();
1401   const int *conn=_nodal_connec->getConstPointer();
1402   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1403   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1404   std::vector<bool> retS(maxElt,false);
1405   for(int i=0;i<nbOfCells;i++)
1406     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1407       if(conn[j]>=0)
1408         retS[conn[j]]=true;
1409   int sz=0;
1410   for(int i=0;i<maxElt;i++)
1411     if(retS[i])
1412       sz++;
1413   DataArrayInt *ret=DataArrayInt::New();
1414   ret->alloc(sz,1);
1415   int *retPtr=ret->getPointer();
1416   for(int i=0;i<maxElt;i++)
1417     if(retS[i])
1418       *retPtr++=i;
1419   return ret;
1420 }
1421
1422 /*!
1423  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1424  * \sa MEDCouplingUMesh::getNodeIdsInUse
1425  */
1426 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1427 {
1428   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1429   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1430   for(int i=0;i<nbOfCells;i++)
1431     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1432       if(conn[j]>=0)
1433         {
1434           if(conn[j]<nbOfNodes)
1435             nodeIdsInUse[conn[j]]=true;
1436           else
1437             {
1438               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1439               throw INTERP_KERNEL::Exception(oss.str().c_str());
1440             }
1441         }
1442 }
1443
1444 /*!
1445  * Finds nodes not used in any cell and returns an array giving a new id to every node
1446  * by excluding the unused nodes, for which the array holds -1. The result array is
1447  * a mapping in "Old to New" mode. 
1448  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1449  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1450  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1451  *          if the node is unused or a new id else. The caller is to delete this
1452  *          array using decrRef() as it is no more needed.  
1453  *  \throw If the coordinates array is not set.
1454  *  \throw If the nodal connectivity of cells is not defined.
1455  *  \throw If the nodal connectivity includes an invalid id.
1456  *
1457  *  \if ENABLE_EXAMPLES
1458  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1459  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1460  *  \endif
1461  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1462  */
1463 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1464 {
1465   nbrOfNodesInUse=-1;
1466   int nbOfNodes(getNumberOfNodes());
1467   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1468   ret->alloc(nbOfNodes,1);
1469   int *traducer=ret->getPointer();
1470   std::fill(traducer,traducer+nbOfNodes,-1);
1471   int nbOfCells=getNumberOfCells();
1472   const int *connIndex=_nodal_connec_index->getConstPointer();
1473   const int *conn=_nodal_connec->getConstPointer();
1474   for(int i=0;i<nbOfCells;i++)
1475     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1476       if(conn[j]>=0)
1477         {
1478           if(conn[j]<nbOfNodes)
1479             traducer[conn[j]]=1;
1480           else
1481             {
1482               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1483               throw INTERP_KERNEL::Exception(oss.str().c_str());
1484             }
1485         }
1486   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1487   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1488   return ret.retn();
1489 }
1490
1491 /*!
1492  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1493  * For each cell in \b this the number of nodes constituting cell is computed.
1494  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1495  * So for pohyhedrons some nodes can be counted several times in the returned result.
1496  * 
1497  * \return a newly allocated array
1498  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1499  */
1500 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1501 {
1502   checkConnectivityFullyDefined();
1503   int nbOfCells=getNumberOfCells();
1504   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1505   ret->alloc(nbOfCells,1);
1506   int *retPtr=ret->getPointer();
1507   const int *conn=getNodalConnectivity()->getConstPointer();
1508   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1509   for(int i=0;i<nbOfCells;i++,retPtr++)
1510     {
1511       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1512         *retPtr=connI[i+1]-connI[i]-1;
1513       else
1514         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1515     }
1516   return ret.retn();
1517 }
1518
1519 /*!
1520  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1521  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1522  *
1523  * \return DataArrayInt * - new object to be deallocated by the caller.
1524  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1525  */
1526 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1527 {
1528   checkConnectivityFullyDefined();
1529   int nbOfCells=getNumberOfCells();
1530   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1531   ret->alloc(nbOfCells,1);
1532   int *retPtr=ret->getPointer();
1533   const int *conn=getNodalConnectivity()->getConstPointer();
1534   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1535   for(int i=0;i<nbOfCells;i++,retPtr++)
1536     {
1537       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1538       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1539         *retPtr=(int)s.size();
1540       else
1541         {
1542           s.erase(-1);
1543           *retPtr=(int)s.size();
1544         }
1545     }
1546   return ret.retn();
1547 }
1548
1549 /*!
1550  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1551  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1552  * 
1553  * \return a newly allocated array
1554  */
1555 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1556 {
1557   checkConnectivityFullyDefined();
1558   int nbOfCells=getNumberOfCells();
1559   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1560   ret->alloc(nbOfCells,1);
1561   int *retPtr=ret->getPointer();
1562   const int *conn=getNodalConnectivity()->getConstPointer();
1563   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1564   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1565     {
1566       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1567       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1568     }
1569   return ret.retn();
1570 }
1571
1572 /*!
1573  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1574  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1575  * array mean that the corresponding old node is no more used. 
1576  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1577  *           this->getNumberOfNodes() before call of this method. The caller is to
1578  *           delete this array using decrRef() as it is no more needed. 
1579  *  \throw If the coordinates array is not set.
1580  *  \throw If the nodal connectivity of cells is not defined.
1581  *  \throw If the nodal connectivity includes an invalid id.
1582  *
1583  *  \if ENABLE_EXAMPLES
1584  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1585  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1586  *  \endif
1587  */
1588 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1589 {
1590   return MEDCouplingPointSet::zipCoordsTraducer();
1591 }
1592
1593 /*!
1594  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1595  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1596  */
1597 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1598 {
1599   switch(compType)
1600   {
1601     case 0:
1602       return AreCellsEqual0(conn,connI,cell1,cell2);
1603     case 1:
1604       return AreCellsEqual1(conn,connI,cell1,cell2);
1605     case 2:
1606       return AreCellsEqual2(conn,connI,cell1,cell2);
1607     case 3:
1608       return AreCellsEqual3(conn,connI,cell1,cell2);
1609     case 7:
1610       return AreCellsEqual7(conn,connI,cell1,cell2);
1611   }
1612   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1613 }
1614
1615 /*!
1616  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1617  */
1618 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1619 {
1620   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1621     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1622   return 0;
1623 }
1624
1625 /*!
1626  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1627  */
1628 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1629 {
1630   int sz=connI[cell1+1]-connI[cell1];
1631   if(sz==connI[cell2+1]-connI[cell2])
1632     {
1633       if(conn[connI[cell1]]==conn[connI[cell2]])
1634         {
1635           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1636           unsigned dim=cm.getDimension();
1637           if(dim!=3)
1638             {
1639               if(dim!=1)
1640                 {
1641                   int sz1=2*(sz-1);
1642                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1643                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1644                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1645                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1646                   return work!=tmp+sz1?1:0;
1647                 }
1648               else
1649                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1650             }
1651           else
1652             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1653         }
1654     }
1655   return 0;
1656 }
1657
1658 /*!
1659  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1660  */
1661 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1662 {
1663   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1664     {
1665       if(conn[connI[cell1]]==conn[connI[cell2]])
1666         {
1667           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1668           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1669           return s1==s2?1:0;
1670         }
1671     }
1672   return 0;
1673 }
1674
1675 /*!
1676  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1677  */
1678 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1679 {
1680   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1681     {
1682       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1683       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1684       return s1==s2?1:0;
1685     }
1686   return 0;
1687 }
1688
1689 /*!
1690  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1691  */
1692 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1693 {
1694   int sz=connI[cell1+1]-connI[cell1];
1695   if(sz==connI[cell2+1]-connI[cell2])
1696     {
1697       if(conn[connI[cell1]]==conn[connI[cell2]])
1698         {
1699           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1700           unsigned dim=cm.getDimension();
1701           if(dim!=3)
1702             {
1703               if(dim!=1)
1704                 {
1705                   int sz1=2*(sz-1);
1706                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1707                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1708                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1709                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1710                   if(work!=tmp+sz1)
1711                     return 1;
1712                   else
1713                     {
1714                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1715                       std::reverse_iterator<int *> it2((int *)tmp);
1716                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1717                         return 2;
1718                       else
1719                         return 0;
1720                     }
1721
1722                   return work!=tmp+sz1?1:0;
1723                 }
1724               else
1725                 {//case of SEG2 and SEG3
1726                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1727                     return 1;
1728                   if(!cm.isQuadratic())
1729                     {
1730                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1731                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1732                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1733                         return 2;
1734                       return 0;
1735                     }
1736                   else
1737                     {
1738                       if(conn[connI[cell1]+1]==conn[connI[cell2]+2] && conn[connI[cell1]+2]==conn[connI[cell2]+1] && conn[connI[cell1]+3]==conn[connI[cell2]+3])
1739                         return 2;
1740                       return 0;
1741                     }
1742                 }
1743             }
1744           else
1745             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1746         }
1747     }
1748   return 0;
1749 }
1750
1751 /*!
1752  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1753  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1754  * and result remains unchanged.
1755  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1756  * If in 'candidates' pool -1 value is considered as an empty value.
1757  * WARNING this method returns only ONE set of result !
1758  */
1759 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1760 {
1761   if(candidates.size()<1)
1762     return false;
1763   bool ret=false;
1764   std::vector<int>::const_iterator iter=candidates.begin();
1765   int start=(*iter++);
1766   for(;iter!=candidates.end();iter++)
1767     {
1768       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1769       if(status!=0)
1770         {
1771           if(!ret)
1772             {
1773               result->pushBackSilent(start);
1774               ret=true;
1775             }
1776           if(status==1)
1777             result->pushBackSilent(*iter);
1778           else
1779             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1780         }
1781     }
1782   return ret;
1783 }
1784
1785 /*!
1786  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1787  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1788  *
1789  * \param [in] compType input specifying the technique used to compare cells each other.
1790  *   - 0 : exactly. A cell is detected to be the same if and only if the connectivity is exactly the same without permutation and types same too. This is the strongest policy.
1791  *   - 1 : permutation same orientation. cell1 and cell2 are considered equal if the connectivity of cell2 can be deduced by those of cell1 by direct permutation (with exactly the same orientation)
1792  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1793  *   - 2 : nodal. cell1 and cell2 are equal if and only if cell1 and cell2 have same type and have the same nodes constituting connectivity. This is the laziest policy. This policy
1794  * can be used for users not sensitive to orientation of cell
1795  * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned.
1796  * \param [out] commonCells
1797  * \param [out] commonCellsI
1798  * \return the correspondance array old to new in a newly allocated array.
1799  * 
1800  */
1801 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1802 {
1803   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1804   getReverseNodalConnectivity(revNodal,revNodalI);
1805   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1806 }
1807
1808 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1809                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1810 {
1811   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1812   int nbOfCells=nodalI->getNumberOfTuples()-1;
1813   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1814   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1815   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1816   std::vector<bool> isFetched(nbOfCells,false);
1817   if(startCellId==0)
1818     {
1819       for(int i=0;i<nbOfCells;i++)
1820         {
1821           if(!isFetched[i])
1822             {
1823               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1824               std::vector<int> v,v2;
1825               if(connOfNode!=connPtr+connIPtr[i+1])
1826                 {
1827                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1828                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1829                   connOfNode++;
1830                 }
1831               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1832                 if(*connOfNode>=0)
1833                   {
1834                     v=v2;
1835                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1836                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1837                     v2.resize(std::distance(v2.begin(),it));
1838                   }
1839               if(v2.size()>1)
1840                 {
1841                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1842                     {
1843                       int pos=commonCellsI->back();
1844                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1845                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1846                         isFetched[*it]=true;
1847                     }
1848                 }
1849             }
1850         }
1851     }
1852   else
1853     {
1854       for(int i=startCellId;i<nbOfCells;i++)
1855         {
1856           if(!isFetched[i])
1857             {
1858               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1859               std::vector<int> v,v2;
1860               if(connOfNode!=connPtr+connIPtr[i+1])
1861                 {
1862                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1863                   connOfNode++;
1864                 }
1865               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1866                 if(*connOfNode>=0)
1867                   {
1868                     v=v2;
1869                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1870                     v2.resize(std::distance(v2.begin(),it));
1871                   }
1872               if(v2.size()>1)
1873                 {
1874                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1875                     {
1876                       int pos=commonCellsI->back();
1877                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1878                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1879                         isFetched[*it]=true;
1880                     }
1881                 }
1882             }
1883         }
1884     }
1885   commonCellsArr=commonCells.retn();
1886   commonCellsIArr=commonCellsI.retn();
1887 }
1888
1889 /*!
1890  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1891  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1892  * than \a other->getNumberOfCells() in the returned array means that there is no
1893  * corresponding cell in \a this mesh.
1894  * It is expected that \a this and \a other meshes share the same node coordinates
1895  * array, if it is not so an exception is thrown. 
1896  *  \param [in] other - the mesh to compare with.
1897  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1898  *         valid values [0,1,2], see zipConnectivityTraducer().
1899  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1900  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1901  *         values. The caller is to delete this array using
1902  *         decrRef() as it is no more needed.
1903  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1904  *         mesh.
1905  *
1906  *  \if ENABLE_EXAMPLES
1907  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1908  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1909  *  \endif
1910  *  \sa checkDeepEquivalOnSameNodesWith()
1911  *  \sa checkGeoEquivalWith()
1912  */
1913 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1914 {
1915   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1916   int nbOfCells=getNumberOfCells();
1917   static const int possibleCompType[]={0,1,2};
1918   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1919     {
1920       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1921       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1922       oss << " !";
1923       throw INTERP_KERNEL::Exception(oss.str().c_str());
1924     }
1925   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1926   arr=o2n->substr(nbOfCells);
1927   arr->setName(other->getName());
1928   int tmp;
1929   if(other->getNumberOfCells()==0)
1930     return true;
1931   return arr->getMaxValue(tmp)<nbOfCells;
1932 }
1933
1934 /*!
1935  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1936  * This method tries to determine if \b other is fully included in \b this.
1937  * The main difference is that this method is not expected to throw exception.
1938  * This method has two outputs :
1939  *
1940  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1941  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1942  */
1943 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1944 {
1945   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1946   DataArrayInt *commonCells=0,*commonCellsI=0;
1947   int thisNbCells=getNumberOfCells();
1948   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1949   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1950   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1951   int otherNbCells=other->getNumberOfCells();
1952   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1953   arr2->alloc(otherNbCells,1);
1954   arr2->fillWithZero();
1955   int *arr2Ptr=arr2->getPointer();
1956   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1957   for(int i=0;i<nbOfCommon;i++)
1958     {
1959       int start=commonCellsPtr[commonCellsIPtr[i]];
1960       if(start<thisNbCells)
1961         {
1962           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1963             {
1964               int sig=commonCellsPtr[j]>0?1:-1;
1965               int val=std::abs(commonCellsPtr[j])-1;
1966               if(val>=thisNbCells)
1967                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1968             }
1969         }
1970     }
1971   arr2->setName(other->getName());
1972   if(arr2->presenceOfValue(0))
1973     return false;
1974   arr=arr2.retn();
1975   return true;
1976 }
1977
1978 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1979 {
1980   if(!other)
1981     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1982   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1983   if(!otherC)
1984     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1985   std::vector<const MEDCouplingUMesh *> ms(2);
1986   ms[0]=this;
1987   ms[1]=otherC;
1988   return MergeUMeshesOnSameCoords(ms);
1989 }
1990
1991 /*!
1992  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1993  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1994  * cellIds is not given explicitely but by a range python like.
1995  * 
1996  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
1997  * \return a newly allocated
1998  * 
1999  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2000  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2001  */
2002 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2003 {
2004   if(getMeshDimension()!=-1)
2005     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2006   else
2007     {
2008       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2009       if(newNbOfCells!=1)
2010         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2011       if(start!=0)
2012         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2013       incrRef();
2014       return const_cast<MEDCouplingUMesh *>(this);
2015     }
2016 }
2017
2018 /*!
2019  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2020  * The result mesh shares or not the node coordinates array with \a this mesh depending
2021  * on \a keepCoords parameter.
2022  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2023  *           to write this mesh to the MED file, its cells must be sorted using
2024  *           sortCellsInMEDFileFrmt().
2025  *  \param [in] begin - an array of cell ids to include to the new mesh.
2026  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2027  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2028  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2029  *         by calling zipCoords().
2030  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2031  *         to delete this mesh using decrRef() as it is no more needed. 
2032  *  \throw If the coordinates array is not set.
2033  *  \throw If the nodal connectivity of cells is not defined.
2034  *  \throw If any cell id in the array \a begin is not valid.
2035  *
2036  *  \if ENABLE_EXAMPLES
2037  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2038  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2039  *  \endif
2040  */
2041 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2042 {
2043   if(getMeshDimension()!=-1)
2044     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2045   else
2046     {
2047       if(end-begin!=1)
2048         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2049       if(begin[0]!=0)
2050         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2051       incrRef();
2052       return const_cast<MEDCouplingUMesh *>(this);
2053     }
2054 }
2055
2056 /*!
2057  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2058  *
2059  * This method allows to partially modify some cells in \b this (whose list is specified by [ \b cellIdsBg, \b cellIdsEnd ) ) with cells coming in \b otherOnSameCoordsThanThis.
2060  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2061  * The number of cells of \b this will remain the same with this method.
2062  *
2063  * \param [in] begin begin of cell ids (included) of cells in this to assign
2064  * \param [in] end end of cell ids (excluded) of cells in this to assign
2065  * \param [in] otherOnSameCoordsThanThis an another mesh with same meshdimension than \b this with exactly the same number of cells than cell ids list in [\b cellIdsBg, \b cellIdsEnd ).
2066  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2067  */
2068 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2069 {
2070   checkConnectivityFullyDefined();
2071   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2072   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2073     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2074   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2075     {
2076       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2077       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2078       throw INTERP_KERNEL::Exception(oss.str().c_str());
2079     }
2080   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2081   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2082     {
2083       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2084       throw INTERP_KERNEL::Exception(oss.str().c_str());
2085     }
2086   int nbOfCells=getNumberOfCells();
2087   bool easyAssign=true;
2088   const int *connI=_nodal_connec_index->getConstPointer();
2089   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2090   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2091     {
2092       if(*it>=0 && *it<nbOfCells)
2093         {
2094           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2095         }
2096       else
2097         {
2098           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2099           throw INTERP_KERNEL::Exception(oss.str().c_str());
2100         }
2101     }
2102   if(easyAssign)
2103     {
2104       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2105       computeTypes();
2106     }
2107   else
2108     {
2109       DataArrayInt *arrOut=0,*arrIOut=0;
2110       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2111                                                arrOut,arrIOut);
2112       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2113       setConnectivity(arrOut,arrIOut,true);
2114     }
2115 }
2116
2117 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2118 {
2119   checkConnectivityFullyDefined();
2120   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2121   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2122     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2123   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2124     {
2125       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2126       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2127       throw INTERP_KERNEL::Exception(oss.str().c_str());
2128     }
2129   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2130   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2131     {
2132       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2133       throw INTERP_KERNEL::Exception(oss.str().c_str());
2134     }
2135   int nbOfCells=getNumberOfCells();
2136   bool easyAssign=true;
2137   const int *connI=_nodal_connec_index->getConstPointer();
2138   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2139   int it=start;
2140   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2141     {
2142       if(it>=0 && it<nbOfCells)
2143         {
2144           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2145         }
2146       else
2147         {
2148           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2149           throw INTERP_KERNEL::Exception(oss.str().c_str());
2150         }
2151     }
2152   if(easyAssign)
2153     {
2154       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2155       computeTypes();
2156     }
2157   else
2158     {
2159       DataArrayInt *arrOut=0,*arrIOut=0;
2160       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2161                                                 arrOut,arrIOut);
2162       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2163       setConnectivity(arrOut,arrIOut,true);
2164     }
2165 }                      
2166
2167 /*!
2168  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2169  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2170  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2171  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2172  *
2173  * \param [in] begin input start of array of node ids.
2174  * \param [in] end input end of array of node ids.
2175  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2176  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2177  */
2178 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2179 {
2180   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2181   checkConnectivityFullyDefined();
2182   int tmp=-1;
2183   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2184   std::vector<bool> fastFinder(sz,false);
2185   for(const int *work=begin;work!=end;work++)
2186     if(*work>=0 && *work<sz)
2187       fastFinder[*work]=true;
2188   int nbOfCells=getNumberOfCells();
2189   const int *conn=getNodalConnectivity()->getConstPointer();
2190   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2191   for(int i=0;i<nbOfCells;i++)
2192     {
2193       int ref=0,nbOfHit=0;
2194       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2195         if(*work2>=0)
2196           {
2197             ref++;
2198             if(fastFinder[*work2])
2199               nbOfHit++;
2200           }
2201       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2202         cellIdsKept->pushBackSilent(i);
2203     }
2204   cellIdsKeptArr=cellIdsKept.retn();
2205 }
2206
2207 /*!
2208  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2209  * this->getMeshDimension(), that bound some cells of \a this mesh.
2210  * The cells of lower dimension to include to the result mesh are selected basing on
2211  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2212  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2213  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2214  * created mesh shares the node coordinates array with \a this mesh. 
2215  *  \param [in] begin - the array of node ids.
2216  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2217  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2218  *         array \a begin are added, else cells whose any node is in the
2219  *         array \a begin are added.
2220  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2221  *         to delete this mesh using decrRef() as it is no more needed. 
2222  *  \throw If the coordinates array is not set.
2223  *  \throw If the nodal connectivity of cells is not defined.
2224  *  \throw If any node id in \a begin is not valid.
2225  *
2226  *  \if ENABLE_EXAMPLES
2227  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2228  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2229  *  \endif
2230  */
2231 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2232 {
2233   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2234   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2235   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2236   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2237   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2238 }
2239
2240 /*!
2241  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2242  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2243  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2244  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2245  *         by calling zipCoords().
2246  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2247  *         to delete this mesh using decrRef() as it is no more needed. 
2248  *  \throw If the coordinates array is not set.
2249  *  \throw If the nodal connectivity of cells is not defined.
2250  *
2251  *  \if ENABLE_EXAMPLES
2252  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2253  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2254  *  \endif
2255  */
2256 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2257 {
2258   DataArrayInt *desc=DataArrayInt::New();
2259   DataArrayInt *descIndx=DataArrayInt::New();
2260   DataArrayInt *revDesc=DataArrayInt::New();
2261   DataArrayInt *revDescIndx=DataArrayInt::New();
2262   //
2263   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2264   revDesc->decrRef();
2265   desc->decrRef();
2266   descIndx->decrRef();
2267   int nbOfCells=meshDM1->getNumberOfCells();
2268   const int *revDescIndxC=revDescIndx->getConstPointer();
2269   std::vector<int> boundaryCells;
2270   for(int i=0;i<nbOfCells;i++)
2271     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2272       boundaryCells.push_back(i);
2273   revDescIndx->decrRef();
2274   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2275   return ret;
2276 }
2277
2278 /*!
2279  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2280  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2281  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2282  */
2283 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2284 {
2285   checkFullyDefined();
2286   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2287   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2288   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2290   //
2291   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2292   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2293   //
2294   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2295   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2296   const int *revDescPtr=revDesc->getConstPointer();
2297   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2298   int nbOfCells=getNumberOfCells();
2299   std::vector<bool> ret1(nbOfCells,false);
2300   int sz=0;
2301   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2302     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2303       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2304   //
2305   DataArrayInt *ret2=DataArrayInt::New();
2306   ret2->alloc(sz,1);
2307   int *ret2Ptr=ret2->getPointer();
2308   sz=0;
2309   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2310     if(*it)
2311       *ret2Ptr++=sz;
2312   ret2->setName("BoundaryCells");
2313   return ret2;
2314 }
2315
2316 /*!
2317  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2318  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2319  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2320  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2321  *
2322  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2323  * This method method returns cells ids set s = s1 + s2 where :
2324  * 
2325  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2326  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2327  *
2328  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2329  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2330  *
2331  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2332  * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2333  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2334  */
2335 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2336 {
2337   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2338     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2339   checkConnectivityFullyDefined();
2340   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2341   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2342     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2345   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2347   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2348   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2349   DataArrayInt *idsOtherInConsti=0;
2350   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2351   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2352   if(!b)
2353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2354   std::set<int> s1;
2355   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2356     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2357   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2359   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2360   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2362   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2363   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2364   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2365   neighThisPartAuto=0;
2366   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2367   const int li[2]={0,1};
2368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2369   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2371   s_renum1->sort();
2372   //
2373   cellIdsRk0=s0arr.retn();
2374   cellIdsRk1=s_renum1.retn();
2375 }
2376
2377 /*!
2378  * This method computes the skin of \b this. That is to say the consituting meshdim-1 mesh is built and only the boundary subpart is
2379  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2380  * 
2381  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2382  */
2383 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2384 {
2385   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2386   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2387   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2389   //
2390   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2391   revDesc=0; desc=0; descIndx=0;
2392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2393   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2394   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2395 }
2396
2397 /*!
2398  * Finds nodes lying on the boundary of \a this mesh.
2399  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2400  *          nodes. The caller is to delete this array using decrRef() as it is no
2401  *          more needed.
2402  *  \throw If the coordinates array is not set.
2403  *  \throw If the nodal connectivity of cells is node defined.
2404  *
2405  *  \if ENABLE_EXAMPLES
2406  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2407  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2408  *  \endif
2409  */
2410 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2411 {
2412   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2413   return skin->computeFetchedNodeIds();
2414 }
2415
2416 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2417 {
2418   incrRef();
2419   return const_cast<MEDCouplingUMesh *>(this);
2420 }
2421
2422 /*!
2423  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2424  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2425  * This method searches for nodes needed to be duplicated. These nodes are nodes fetched by \b otherDimM1OnSameCoords which are not part of the boundary of \b otherDimM1OnSameCoords.
2426  * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considerd as needed to be duplicated.
2427  * When the set of node ids \b nodeIdsToDuplicate is computed, cell ids in \b this is searched so that their connectivity includes at least 1 node in \b nodeIdsToDuplicate.
2428  *
2429  * \param [in] otherDimM1OnSameCoords a mesh lying on the same coords than \b this and with a mesh dimension equal to those of \b this minus 1. WARNING this input
2430  *             parameter is altered during the call.
2431  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2432  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2433  * \param [out] cellIdsNotModified cell ids int \b this that lies on \b otherDimM1OnSameCoords mesh whose connectivity do \b not need to be modified as it is the case for \b cellIdsNeededToBeRenum.
2434  *
2435  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2436  */
2437 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2438                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2439 {
2440   checkFullyDefined();
2441   otherDimM1OnSameCoords.checkFullyDefined();
2442   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2443     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2444   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2445     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2446   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2447   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2448   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2449   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2450   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2451   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2452   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2453   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2454   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2455   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2456   //
2457   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2459   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2460   DataArrayInt *idsTmp=0;
2461   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2463   if(!b)
2464     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2465   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2466   DataArrayInt *tmp0=0,*tmp1=0;
2467   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2468   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2469   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2472   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2473   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2474   //
2475   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2476   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2477   nodeIdsToDuplicate=s3.retn();
2478 }
2479
2480 /*!
2481  * This method operates a modification of the connectivity and coords in \b this.
2482  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2483  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2484  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2485  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2486  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2487  * 
2488  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2489  * 
2490  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2491  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2492  */
2493 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2494 {
2495   int nbOfNodes=getNumberOfNodes();
2496   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2497   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2498 }
2499
2500 /*!
2501  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2502  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2503  *
2504  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2505  *
2506  * \sa renumberNodesInConn
2507  */
2508 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2509 {
2510   checkConnectivityFullyDefined();
2511   int *conn(getNodalConnectivity()->getPointer());
2512   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2513   int nbOfCells(getNumberOfCells());
2514   for(int i=0;i<nbOfCells;i++)
2515     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2516       {
2517         int& node=conn[iconn];
2518         if(node>=0)//avoid polyhedron separator
2519           {
2520             node+=offset;
2521           }
2522       }
2523   _nodal_connec->declareAsNew();
2524   updateTime();
2525 }
2526
2527 /*!
2528  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2529  *  of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
2530  *  of a big mesh.
2531  */
2532 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2533 {
2534   checkConnectivityFullyDefined();
2535   int *conn(getNodalConnectivity()->getPointer());
2536   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2537   int nbOfCells(getNumberOfCells());
2538   for(int i=0;i<nbOfCells;i++)
2539     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2540       {
2541         int& node=conn[iconn];
2542         if(node>=0)//avoid polyhedron separator
2543           {
2544             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2545             if(it!=newNodeNumbersO2N.end())
2546               {
2547                 node=(*it).second;
2548               }
2549             else
2550               {
2551                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2552                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2553               }
2554           }
2555       }
2556   _nodal_connec->declareAsNew();
2557   updateTime();
2558 }
2559
2560 /*!
2561  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2562  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2563  * This method is a generalization of shiftNodeNumbersInConn().
2564  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2565  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2566  *         this->getNumberOfNodes(), in "Old to New" mode. 
2567  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2568  *  \throw If the nodal connectivity of cells is not defined.
2569  *
2570  *  \if ENABLE_EXAMPLES
2571  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2572  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2573  *  \endif
2574  */
2575 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2576 {
2577   checkConnectivityFullyDefined();
2578   int *conn=getNodalConnectivity()->getPointer();
2579   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2580   int nbOfCells(getNumberOfCells());
2581   for(int i=0;i<nbOfCells;i++)
2582     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2583       {
2584         int& node=conn[iconn];
2585         if(node>=0)//avoid polyhedron separator
2586           {
2587             node=newNodeNumbersO2N[node];
2588           }
2589       }
2590   _nodal_connec->declareAsNew();
2591   updateTime();
2592 }
2593
2594 /*!
2595  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2596  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2597  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2598  * 
2599  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2600  */
2601 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2602 {
2603   checkConnectivityFullyDefined();
2604   int *conn=getNodalConnectivity()->getPointer();
2605   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2606   int nbOfCells=getNumberOfCells();
2607   for(int i=0;i<nbOfCells;i++)
2608     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2609       {
2610         int& node=conn[iconn];
2611         if(node>=0)//avoid polyhedron separator
2612           {
2613             node+=delta;
2614           }
2615       }
2616   _nodal_connec->declareAsNew();
2617   updateTime();
2618 }
2619
2620 /*!
2621  * This method operates a modification of the connectivity in \b this.
2622  * Coordinates are \b NOT considered here and will remain unchanged by this method. this->_coords can ever been null for the needs of this method.
2623  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2624  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2625  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2626  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2627  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2628  * 
2629  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2630  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2631  * 
2632  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2633  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2634  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2635  */
2636 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2637 {
2638   checkConnectivityFullyDefined();
2639   std::map<int,int> m;
2640   int val=offset;
2641   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2642     m[*work]=val;
2643   int *conn=getNodalConnectivity()->getPointer();
2644   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2645   int nbOfCells=getNumberOfCells();
2646   for(int i=0;i<nbOfCells;i++)
2647     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2648       {
2649         int& node=conn[iconn];
2650         if(node>=0)//avoid polyhedron separator
2651           {
2652             std::map<int,int>::iterator it=m.find(node);
2653             if(it!=m.end())
2654               node=(*it).second;
2655           }
2656       }
2657   updateTime();
2658 }
2659
2660 /*!
2661  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2662  *
2663  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2664  * After the call of this method the number of cells remains the same as before.
2665  *
2666  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2667  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2668  * be strictly in [0;this->getNumberOfCells()).
2669  *
2670  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2671  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2672  * should be contained in[0;this->getNumberOfCells()).
2673  * 
2674  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2675  */
2676 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2677 {
2678   checkConnectivityFullyDefined();
2679   int nbCells=getNumberOfCells();
2680   const int *array=old2NewBg;
2681   if(check)
2682     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2683   //
2684   const int *conn=_nodal_connec->getConstPointer();
2685   const int *connI=_nodal_connec_index->getConstPointer();
2686   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2687   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2688   const int *n2oPtr=n2o->begin();
2689   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2690   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2691   newConn->copyStringInfoFrom(*_nodal_connec);
2692   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2693   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2694   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2695   //
2696   int *newC=newConn->getPointer();
2697   int *newCI=newConnI->getPointer();
2698   int loc=0;
2699   newCI[0]=loc;
2700   for(int i=0;i<nbCells;i++)
2701     {
2702       int pos=n2oPtr[i];
2703       int nbOfElts=connI[pos+1]-connI[pos];
2704       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2705       loc+=nbOfElts;
2706       newCI[i+1]=loc;
2707     }
2708   //
2709   setConnectivity(newConn,newConnI);
2710   if(check)
2711     free(const_cast<int *>(array));
2712 }
2713
2714 /*!
2715  * Finds cells whose bounding boxes intersect a given bounding box.
2716  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2717  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2718  *         zMax (if in 3D). 
2719  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2720  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2721  *         extent of the bounding box of cell to produce an addition to this bounding box.
2722  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2723  *         cells. The caller is to delete this array using decrRef() as it is no more
2724  *         needed. 
2725  *  \throw If the coordinates array is not set.
2726  *  \throw If the nodal connectivity of cells is not defined.
2727  *
2728  *  \if ENABLE_EXAMPLES
2729  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2730  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2731  *  \endif
2732  */
2733 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2734 {
2735   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2736   if(getMeshDimension()==-1)
2737     {
2738       elems->pushBackSilent(0);
2739       return elems.retn();
2740     }
2741   int dim=getSpaceDimension();
2742   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2743   const int* conn      = getNodalConnectivity()->getConstPointer();
2744   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2745   const double* coords = getCoords()->getConstPointer();
2746   int nbOfCells=getNumberOfCells();
2747   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2748     {
2749       for (int i=0; i<dim; i++)
2750         {
2751           elem_bb[i*2]=std::numeric_limits<double>::max();
2752           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2753         }
2754
2755       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2756         {
2757           int node= conn[inode];
2758           if(node>=0)//avoid polyhedron separator
2759             {
2760               for (int idim=0; idim<dim; idim++)
2761                 {
2762                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2763                     {
2764                       elem_bb[idim*2] = coords[node*dim+idim] ;
2765                     }
2766                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2767                     {
2768                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2769                     }
2770                 }
2771             }
2772         }
2773       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2774         elems->pushBackSilent(ielem);
2775     }
2776   return elems.retn();
2777 }
2778
2779 /*!
2780  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2781  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2782  * added in 'elems' parameter.
2783  */
2784 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2785 {
2786   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2787   if(getMeshDimension()==-1)
2788     {
2789       elems->pushBackSilent(0);
2790       return elems.retn();
2791     }
2792   int dim=getSpaceDimension();
2793   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2794   const int* conn      = getNodalConnectivity()->getConstPointer();
2795   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2796   const double* coords = getCoords()->getConstPointer();
2797   int nbOfCells=getNumberOfCells();
2798   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2799     {
2800       for (int i=0; i<dim; i++)
2801         {
2802           elem_bb[i*2]=std::numeric_limits<double>::max();
2803           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2804         }
2805
2806       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2807         {
2808           int node= conn[inode];
2809           if(node>=0)//avoid polyhedron separator
2810             {
2811               for (int idim=0; idim<dim; idim++)
2812                 {
2813                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2814                     {
2815                       elem_bb[idim*2] = coords[node*dim+idim] ;
2816                     }
2817                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2818                     {
2819                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2820                     }
2821                 }
2822             }
2823         }
2824       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2825         elems->pushBackSilent(ielem);
2826     }
2827   return elems.retn();
2828 }
2829
2830 /*!
2831  * Returns a type of a cell by its id.
2832  *  \param [in] cellId - the id of the cell of interest.
2833  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2834  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2835  */
2836 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2837 {
2838   const int *ptI=_nodal_connec_index->getConstPointer();
2839   const int *pt=_nodal_connec->getConstPointer();
2840   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2841     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2842   else
2843     {
2844       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2845       throw INTERP_KERNEL::Exception(oss.str().c_str());
2846     }
2847 }
2848
2849 /*!
2850  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2851  * This method does not throw exception if geometric type \a type is not in \a this.
2852  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2853  * The coordinates array is not considered here.
2854  *
2855  * \param [in] type the geometric type
2856  * \return cell ids in this having geometric type \a type.
2857  */
2858 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2859 {
2860
2861   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2862   ret->alloc(0,1);
2863   checkConnectivityFullyDefined();
2864   int nbCells=getNumberOfCells();
2865   int mdim=getMeshDimension();
2866   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2867   if(mdim!=(int)cm.getDimension())
2868     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2869   const int *ptI=_nodal_connec_index->getConstPointer();
2870   const int *pt=_nodal_connec->getConstPointer();
2871   for(int i=0;i<nbCells;i++)
2872     {
2873       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2874         ret->pushBackSilent(i);
2875     }
2876   return ret.retn();
2877 }
2878
2879 /*!
2880  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2881  */
2882 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2883 {
2884   const int *ptI=_nodal_connec_index->getConstPointer();
2885   const int *pt=_nodal_connec->getConstPointer();
2886   int nbOfCells=getNumberOfCells();
2887   int ret=0;
2888   for(int i=0;i<nbOfCells;i++)
2889     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2890       ret++;
2891   return ret;
2892 }
2893
2894 /*!
2895  * Returns the nodal connectivity of a given cell.
2896  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2897  * all returned node ids can be used in getCoordinatesOfNode().
2898  *  \param [in] cellId - an id of the cell of interest.
2899  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2900  *         cleared before the appending.
2901  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2902  */
2903 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2904 {
2905   const int *ptI=_nodal_connec_index->getConstPointer();
2906   const int *pt=_nodal_connec->getConstPointer();
2907   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2908     if(*w>=0)
2909       conn.push_back(*w);
2910 }
2911
2912 std::string MEDCouplingUMesh::simpleRepr() const
2913 {
2914   static const char msg0[]="No coordinates specified !";
2915   std::ostringstream ret;
2916   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2917   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2918   int tmpp1,tmpp2;
2919   double tt=getTime(tmpp1,tmpp2);
2920   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2921   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2922   if(_mesh_dim>=-1)
2923     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2924   else
2925     { ret << " Mesh dimension has not been set or is invalid !"; }
2926   if(_coords!=0)
2927     {
2928       const int spaceDim=getSpaceDimension();
2929       ret << spaceDim << "\nInfo attached on space dimension : ";
2930       for(int i=0;i<spaceDim;i++)
2931         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2932       ret << "\n";
2933     }
2934   else
2935     ret << msg0 << "\n";
2936   ret << "Number of nodes : ";
2937   if(_coords!=0)
2938     ret << getNumberOfNodes() << "\n";
2939   else
2940     ret << msg0 << "\n";
2941   ret << "Number of cells : ";
2942   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2943     ret << getNumberOfCells() << "\n";
2944   else
2945     ret << "No connectivity specified !" << "\n";
2946   ret << "Cell types present : ";
2947   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2948     {
2949       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2950       ret << cm.getRepr() << " ";
2951     }
2952   ret << "\n";
2953   return ret.str();
2954 }
2955
2956 std::string MEDCouplingUMesh::advancedRepr() const
2957 {
2958   std::ostringstream ret;
2959   ret << simpleRepr();
2960   ret << "\nCoordinates array : \n___________________\n\n";
2961   if(_coords)
2962     _coords->reprWithoutNameStream(ret);
2963   else
2964     ret << "No array set !\n";
2965   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2966   reprConnectivityOfThisLL(ret);
2967   return ret.str();
2968 }
2969
2970 /*!
2971  * This method returns a C++ code that is a dump of \a this.
2972  * This method will throw if this is not fully defined.
2973  */
2974 std::string MEDCouplingUMesh::cppRepr() const
2975 {
2976   static const char coordsName[]="coords";
2977   static const char connName[]="conn";
2978   static const char connIName[]="connI";
2979   checkFullyDefined();
2980   std::ostringstream ret; ret << "// coordinates" << std::endl;
2981   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2982   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2983   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2984   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2985   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2986   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2987   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2988   return ret.str();
2989 }
2990
2991 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2992 {
2993   std::ostringstream ret;
2994   reprConnectivityOfThisLL(ret);
2995   return ret.str();
2996 }
2997
2998 /*!
2999  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3000  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3001  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3002  * some algos).
3003  * 
3004  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3005  * This method analyzes the 3 arrays of \a this. For each the following behaviour is done : if the array is null a newly one is created
3006  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3007  */
3008 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3009 {
3010   int mdim=getMeshDimension();
3011   if(mdim<0)
3012     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3013   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3014   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3015   bool needToCpyCT=true;
3016   if(!_nodal_connec)
3017     {
3018       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3019       needToCpyCT=false;
3020     }
3021   else
3022     {
3023       tmp1=_nodal_connec;
3024       tmp1->incrRef();
3025     }
3026   if(!_nodal_connec_index)
3027     {
3028       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3029       needToCpyCT=false;
3030     }
3031   else
3032     {
3033       tmp2=_nodal_connec_index;
3034       tmp2->incrRef();
3035     }
3036   ret->setConnectivity(tmp1,tmp2,false);
3037   if(needToCpyCT)
3038     ret->_types=_types;
3039   if(!_coords)
3040     {
3041       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3042       ret->setCoords(coords);
3043     }
3044   else
3045     ret->setCoords(_coords);
3046   return ret.retn();
3047 }
3048
3049 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3050 {
3051   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3052     {
3053       int nbOfCells=getNumberOfCells();
3054       const int *c=_nodal_connec->getConstPointer();
3055       const int *ci=_nodal_connec_index->getConstPointer();
3056       for(int i=0;i<nbOfCells;i++)
3057         {
3058           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3059           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3060           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3061           stream << "\n";
3062         }
3063     }
3064   else
3065     stream << "Connectivity not defined !\n";
3066 }
3067
3068 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3069 {
3070   const int *ptI=_nodal_connec_index->getConstPointer();
3071   const int *pt=_nodal_connec->getConstPointer();
3072   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3073     return ptI[cellId+1]-ptI[cellId]-1;
3074   else
3075     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3076 }
3077
3078 /*!
3079  * Returns types of cells of the specified part of \a this mesh.
3080  * This method avoids computing sub-mesh explicitely to get its types.
3081  *  \param [in] begin - an array of cell ids of interest.
3082  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3083  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3084  *         describing the cell types. 
3085  *  \throw If the coordinates array is not set.
3086  *  \throw If the nodal connectivity of cells is not defined.
3087  *  \sa getAllGeoTypes()
3088  */
3089 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3090 {
3091   checkFullyDefined();
3092   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3093   const int *conn=_nodal_connec->getConstPointer();
3094   const int *connIndex=_nodal_connec_index->getConstPointer();
3095   for(const int *w=begin;w!=end;w++)
3096     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3097   return ret;
3098 }
3099
3100 /*!
3101  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3102  * a set of types of cells constituting \a this mesh. 
3103  * This method is for advanced users having prepared their connectivity before. For
3104  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3105  *  \param [in] conn - the nodal connectivity array. 
3106  *  \param [in] connIndex - the nodal connectivity index array.
3107  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3108  *         mesh is updated.
3109  */
3110 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3111 {
3112   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3113   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3114   if(isComputingTypes)
3115     computeTypes();
3116   declareAsNew();
3117 }
3118
3119 /*!
3120  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3121  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3122  */
3123 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3124     _nodal_connec(0),_nodal_connec_index(0),
3125     _types(other._types)
3126 {
3127   if(other._nodal_connec)
3128     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3129   if(other._nodal_connec_index)
3130     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3131 }
3132
3133 MEDCouplingUMesh::~MEDCouplingUMesh()
3134 {
3135   if(_nodal_connec)
3136     _nodal_connec->decrRef();
3137   if(_nodal_connec_index)
3138     _nodal_connec_index->decrRef();
3139 }
3140
3141 /*!
3142  * Recomputes a set of cell types of \a this mesh. For more info see
3143  * \ref MEDCouplingUMeshNodalConnectivity.
3144  */
3145 void MEDCouplingUMesh::computeTypes()
3146 {
3147   if(_nodal_connec && _nodal_connec_index)
3148     {
3149       _types.clear();
3150       const int *conn=_nodal_connec->getConstPointer();
3151       const int *connIndex=_nodal_connec_index->getConstPointer();
3152       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3153       if (nbOfElem > 0)
3154         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3155           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3156     }
3157 }
3158
3159 /*!
3160  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3161  */
3162 void MEDCouplingUMesh::checkFullyDefined() const
3163 {
3164   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3165     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3166 }
3167
3168 /*!
3169  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3170  */
3171 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3172 {
3173   if(!_nodal_connec_index || !_nodal_connec)
3174     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3175 }
3176
3177 /*!
3178  * Returns a number of cells constituting \a this mesh. 
3179  *  \return int - the number of cells in \a this mesh.
3180  *  \throw If the nodal connectivity of cells is not defined.
3181  */
3182 int MEDCouplingUMesh::getNumberOfCells() const
3183
3184   if(_nodal_connec_index)
3185     return _nodal_connec_index->getNumberOfTuples()-1;
3186   else
3187     if(_mesh_dim==-1)
3188       return 1;
3189     else
3190       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3191 }
3192
3193 /*!
3194  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3195  * mesh. For more info see \ref MEDCouplingMeshesPage.
3196  *  \return int - the dimension of \a this mesh.
3197  *  \throw If the mesh dimension is not defined using setMeshDimension().
3198  */
3199 int MEDCouplingUMesh::getMeshDimension() const
3200 {
3201   if(_mesh_dim<-1)
3202     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3203   return _mesh_dim;
3204 }
3205
3206 /*!
3207  * Returns a length of the nodal connectivity array.
3208  * This method is for test reason. Normally the integer returned is not useable by
3209  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3210  *  \return int - the length of the nodal connectivity array.
3211  */
3212 int MEDCouplingUMesh::getMeshLength() const
3213 {
3214   return _nodal_connec->getNbOfElems();
3215 }
3216
3217 /*!
3218  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3219  */
3220 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3221 {
3222   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3223   tinyInfo.push_back(getMeshDimension());
3224   tinyInfo.push_back(getNumberOfCells());
3225   if(_nodal_connec)
3226     tinyInfo.push_back(getMeshLength());
3227   else
3228     tinyInfo.push_back(-1);
3229 }
3230
3231 /*!
3232  * First step of unserialization process.
3233  */
3234 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3235 {
3236   return tinyInfo[6]<=0;
3237 }
3238
3239 /*!
3240  * Second step of serialization process.
3241  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3242  */
3243 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3244 {
3245   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3246   if(tinyInfo[5]!=-1)
3247     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3248 }
3249
3250 /*!
3251  * Third and final step of serialization process.
3252  */
3253 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3254 {
3255   MEDCouplingPointSet::serialize(a1,a2);
3256   if(getMeshDimension()>-1)
3257     {
3258       a1=DataArrayInt::New();
3259       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3260       int *ptA1=a1->getPointer();
3261       const int *conn=getNodalConnectivity()->getConstPointer();
3262       const int *index=getNodalConnectivityIndex()->getConstPointer();
3263       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3264       std::copy(conn,conn+getMeshLength(),ptA1);
3265     }
3266   else
3267     a1=0;
3268 }
3269
3270 /*!
3271  * Second and final unserialization process.
3272  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3273  */
3274 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3275 {
3276   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3277   setMeshDimension(tinyInfo[5]);
3278   if(tinyInfo[7]!=-1)
3279     {
3280       // Connectivity
3281       const int *recvBuffer=a1->getConstPointer();
3282       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3283       myConnecIndex->alloc(tinyInfo[6]+1,1);
3284       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3285       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3286       myConnec->alloc(tinyInfo[7],1);
3287       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3288       setConnectivity(myConnec, myConnecIndex);
3289     }
3290 }
3291
3292 /*!
3293  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3294  * CellIds are given using range specified by a start an end and step.
3295  */
3296 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3297 {
3298   checkFullyDefined();
3299   int ncell=getNumberOfCells();
3300   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3301   ret->_mesh_dim=_mesh_dim;
3302   ret->setCoords(_coords);
3303   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3304   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3305   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3306   int work=start;
3307   const int *conn=_nodal_connec->getConstPointer();
3308   const int *connIndex=_nodal_connec_index->getConstPointer();
3309   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3310     {
3311       if(work>=0 && work<ncell)
3312         {
3313           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3314         }
3315       else
3316         {
3317           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3318           throw INTERP_KERNEL::Exception(oss.str().c_str());
3319         }
3320     }
3321   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3322   int *newConnPtr=newConn->getPointer();
3323   std::set<INTERP_KERNEL::NormalizedCellType> types;
3324   work=start;
3325   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3326     {
3327       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3328       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3329     }
3330   ret->setConnectivity(newConn,newConnI,false);
3331   ret->_types=types;
3332   ret->copyTinyInfoFrom(this);
3333   return ret.retn();
3334 }
3335
3336 /*!
3337  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3338  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3339  * The return newly allocated mesh will share the same coordinates as \a this.
3340  */
3341 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3342 {
3343   checkConnectivityFullyDefined();
3344   int ncell=getNumberOfCells();
3345   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3346   ret->_mesh_dim=_mesh_dim;
3347   ret->setCoords(_coords);
3348   std::size_t nbOfElemsRet=std::distance(begin,end);
3349   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3350   connIndexRet[0]=0;
3351   const int *conn=_nodal_connec->getConstPointer();
3352   const int *connIndex=_nodal_connec_index->getConstPointer();
3353   int newNbring=0;
3354   for(const int *work=begin;work!=end;work++,newNbring++)
3355     {
3356       if(*work>=0 && *work<ncell)
3357         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3358       else
3359         {
3360           free(connIndexRet);
3361           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3362           throw INTERP_KERNEL::Exception(oss.str().c_str());
3363         }
3364     }
3365   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3366   int *connRetWork=connRet;
3367   std::set<INTERP_KERNEL::NormalizedCellType> types;
3368   for(const int *work=begin;work!=end;work++)
3369     {
3370       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3371       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3372     }
3373   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3374   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3375   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3376   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3377   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3378   ret->_types=types;
3379   ret->copyTinyInfoFrom(this);
3380   return ret.retn();
3381 }
3382
3383 /*!
3384  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3385  * mesh.<br>
3386  * For 1D cells, the returned field contains lengths.<br>
3387  * For 2D cells, the returned field contains areas.<br>
3388  * For 3D cells, the returned field contains volumes.
3389  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3390  *         orientation, i.e. the volume is always positive.
3391  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3392  *         and one time . The caller is to delete this field using decrRef() as it is no
3393  *         more needed.
3394  */
3395 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3396 {
3397   std::string name="MeasureOfMesh_";
3398   name+=getName();
3399   int nbelem=getNumberOfCells();
3400   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3401   field->setName(name);
3402   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3403   array->alloc(nbelem,1);
3404   double *area_vol=array->getPointer();
3405   field->setArray(array) ; array=0;
3406   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3407   field->synchronizeTimeWithMesh();
3408   if(getMeshDimension()!=-1)
3409     {
3410       int ipt;
3411       INTERP_KERNEL::NormalizedCellType type;
3412       int dim_space=getSpaceDimension();
3413       const double *coords=getCoords()->getConstPointer();
3414       const int *connec=getNodalConnectivity()->getConstPointer();
3415       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3416       for(int iel=0;iel<nbelem;iel++)
3417         {
3418           ipt=connec_index[iel];
3419           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3420           area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space);
3421         }
3422       if(isAbs)
3423         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3424     }
3425   else
3426     {
3427       area_vol[0]=std::numeric_limits<double>::max();
3428     }
3429   return field.retn();
3430 }
3431
3432 /*!
3433  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3434  * mesh.<br>
3435  * For 1D cells, the returned array contains lengths.<br>
3436  * For 2D cells, the returned array contains areas.<br>
3437  * For 3D cells, the returned array contains volumes.
3438  * This method avoids building explicitly a part of \a this mesh to perform the work.
3439  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3440  *         orientation, i.e. the volume is always positive.
3441  *  \param [in] begin - an array of cell ids of interest.
3442  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3443  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3444  *          delete this array using decrRef() as it is no more needed.
3445  * 
3446  *  \if ENABLE_EXAMPLES
3447  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3448  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3449  *  \endif
3450  *  \sa getMeasureField()
3451  */
3452 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3453 {
3454   std::string name="PartMeasureOfMesh_";
3455   name+=getName();
3456   int nbelem=(int)std::distance(begin,end);
3457   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3458   array->setName(name);
3459   array->alloc(nbelem,1);
3460   double *area_vol=array->getPointer();
3461   if(getMeshDimension()!=-1)
3462     {
3463       int ipt;
3464       INTERP_KERNEL::NormalizedCellType type;
3465       int dim_space=getSpaceDimension();
3466       const double *coords=getCoords()->getConstPointer();
3467       const int *connec=getNodalConnectivity()->getConstPointer();
3468       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3469       for(const int *iel=begin;iel!=end;iel++)
3470         {
3471           ipt=connec_index[*iel];
3472           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3473           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3474         }
3475       if(isAbs)
3476         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3477     }
3478   else
3479     {
3480       area_vol[0]=std::numeric_limits<double>::max();
3481     }
3482   return array.retn();
3483 }
3484
3485 /*!
3486  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3487  * \a this one. The returned field contains the dual cell volume for each corresponding
3488  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3489  *  the dual mesh in P1 sens of \a this.<br>
3490  * For 1D cells, the returned field contains lengths.<br>
3491  * For 2D cells, the returned field contains areas.<br>
3492  * For 3D cells, the returned field contains volumes.
3493  * This method is useful to check "P1*" conservative interpolators.
3494  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3495  *         orientation, i.e. the volume is always positive.
3496  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3497  *          nodes and one time. The caller is to delete this array using decrRef() as
3498  *          it is no more needed.
3499  */
3500 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3501 {
3502   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3503   std::string name="MeasureOnNodeOfMesh_";
3504   name+=getName();
3505   int nbNodes=getNumberOfNodes();
3506   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3507   double cst=1./((double)getMeshDimension()+1.);
3508   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3509   array->alloc(nbNodes,1);
3510   double *valsToFill=array->getPointer();
3511   std::fill(valsToFill,valsToFill+nbNodes,0.);
3512   const double *values=tmp->getArray()->getConstPointer();
3513   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3515   getReverseNodalConnectivity(da,daInd);
3516   const int *daPtr=da->getConstPointer();
3517   const int *daIPtr=daInd->getConstPointer();
3518   for(int i=0;i<nbNodes;i++)
3519     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3520       valsToFill[i]+=cst*values[*cell];
3521   ret->setMesh(this);
3522   ret->setArray(array);
3523   return ret.retn();
3524 }
3525
3526 /*!
3527  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3528  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3529  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3530  * and are normalized.
3531  * <br> \a this can be either 
3532  * - a  2D mesh in 2D or 3D space or 
3533  * - an 1D mesh in 2D space.
3534  * 
3535  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3536  *          cells and one time. The caller is to delete this field using decrRef() as
3537  *          it is no more needed.
3538  *  \throw If the nodal connectivity of cells is not defined.
3539  *  \throw If the coordinates array is not set.
3540  *  \throw If the mesh dimension is not set.
3541  *  \throw If the mesh and space dimension is not as specified above.
3542  */
3543 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3544 {
3545   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3546     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3547   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3548   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3549   int nbOfCells=getNumberOfCells();
3550   int nbComp=getMeshDimension()+1;
3551   array->alloc(nbOfCells,nbComp);
3552   double *vals=array->getPointer();
3553   const int *connI=_nodal_connec_index->getConstPointer();
3554   const int *conn=_nodal_connec->getConstPointer();
3555   const double *coords=_coords->getConstPointer();
3556   if(getMeshDimension()==2)
3557     {
3558       if(getSpaceDimension()==3)
3559         {
3560           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3561           const double *locPtr=loc->getConstPointer();
3562           for(int i=0;i<nbOfCells;i++,vals+=3)
3563             {
3564               int offset=connI[i];
3565               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3566               double n=INTERP_KERNEL::norm<3>(vals);
3567               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3568             }
3569         }
3570       else
3571         {
3572           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3573           const double *isAbsPtr=isAbs->getArray()->begin();
3574           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3575             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3576         }
3577     }
3578   else//meshdimension==1
3579     {
3580       double tmp[2];
3581       for(int i=0;i<nbOfCells;i++)
3582         {
3583           int offset=connI[i];
3584           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3585           double n=INTERP_KERNEL::norm<2>(tmp);
3586           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3587           *vals++=-tmp[1];
3588           *vals++=tmp[0];
3589         }
3590     }
3591   ret->setArray(array);
3592   ret->setMesh(this);
3593   ret->synchronizeTimeWithSupport();
3594   return ret.retn();
3595 }
3596
3597 /*!
3598  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3599  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3600  * and are normalized.
3601  * <br> \a this can be either 
3602  * - a  2D mesh in 2D or 3D space or 
3603  * - an 1D mesh in 2D space.
3604  * 
3605  * This method avoids building explicitly a part of \a this mesh to perform the work.
3606  *  \param [in] begin - an array of cell ids of interest.
3607  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3608  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3609  *          cells and one time. The caller is to delete this field using decrRef() as
3610  *          it is no more needed.
3611  *  \throw If the nodal connectivity of cells is not defined.
3612  *  \throw If the coordinates array is not set.
3613  *  \throw If the mesh dimension is not set.
3614  *  \throw If the mesh and space dimension is not as specified above.
3615  *  \sa buildOrthogonalField()
3616  *
3617  *  \if ENABLE_EXAMPLES
3618  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3619  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3620  *  \endif
3621  */
3622 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3623 {
3624   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3625     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3626   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3627   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3628   std::size_t nbelems=std::distance(begin,end);
3629   int nbComp=getMeshDimension()+1;
3630   array->alloc((int)nbelems,nbComp);
3631   double *vals=array->getPointer();
3632   const int *connI=_nodal_connec_index->getConstPointer();
3633   const int *conn=_nodal_connec->getConstPointer();
3634   const double *coords=_coords->getConstPointer();
3635   if(getMeshDimension()==2)
3636     {
3637       if(getSpaceDimension()==3)
3638         {
3639           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3640           const double *locPtr=loc->getConstPointer();
3641           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3642             {
3643               int offset=connI[*i];
3644               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3645               double n=INTERP_KERNEL::norm<3>(vals);
3646               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3647             }
3648         }
3649       else
3650         {
3651           for(std::size_t i=0;i<nbelems;i++)
3652             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3653         }
3654     }
3655   else//meshdimension==1
3656     {
3657       double tmp[2];
3658       for(const int *i=begin;i!=end;i++)
3659         {
3660           int offset=connI[*i];
3661           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3662           double n=INTERP_KERNEL::norm<2>(tmp);
3663           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3664           *vals++=-tmp[1];
3665           *vals++=tmp[0];
3666         }
3667     }
3668   ret->setArray(array);
3669   ret->setMesh(this);
3670   ret->synchronizeTimeWithSupport();
3671   return ret.retn();
3672 }
3673
3674 /*!
3675  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3676  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3677  * and are \b not normalized.
3678  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3679  *          cells and one time. The caller is to delete this field using decrRef() as
3680  *          it is no more needed.
3681  *  \throw If the nodal connectivity of cells is not defined.
3682  *  \throw If the coordinates array is not set.
3683  *  \throw If \a this->getMeshDimension() != 1.
3684  *  \throw If \a this mesh includes cells of type other than SEG2.
3685  */
3686 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3687 {
3688   if(getMeshDimension()!=1)
3689     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3690   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3691     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3692   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3693   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3694   int nbOfCells=getNumberOfCells();
3695   int spaceDim=getSpaceDimension();
3696   array->alloc(nbOfCells,spaceDim);
3697   double *pt=array->getPointer();
3698   const double *coo=getCoords()->getConstPointer();
3699   std::vector<int> conn;
3700   conn.reserve(2);
3701   for(int i=0;i<nbOfCells;i++)
3702     {
3703       conn.resize(0);
3704       getNodeIdsOfCell(i,conn);
3705       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3706     }
3707   ret->setArray(array);
3708   ret->setMesh(this);
3709   ret->synchronizeTimeWithSupport();
3710   return ret.retn();
3711 }
3712
3713 /*!
3714  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3715  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3716  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3717  * from. If a result face is shared by two 3D cells, then the face in included twice in
3718  * the result mesh.
3719  *  \param [in] origin - 3 components of a point defining location of the plane.
3720  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3721  *         must be greater than 1e-6.
3722  *  \param [in] eps - half-thickness of the plane.
3723  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3724  *         producing correspondent 2D cells. The caller is to delete this array
3725  *         using decrRef() as it is no more needed.
3726  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3727  *         not share the node coordinates array with \a this mesh. The caller is to
3728  *         delete this mesh using decrRef() as it is no more needed.  
3729  *  \throw If the coordinates array is not set.
3730  *  \throw If the nodal connectivity of cells is not defined.
3731  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3732  *  \throw If magnitude of \a vec is less than 1e-6.
3733  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3734  *  \throw If \a this includes quadratic cells.
3735  */
3736 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3737 {
3738   checkFullyDefined();
3739   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3740     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3741   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3742   if(candidates->empty())
3743     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3744   std::vector<int> nodes;
3745   DataArrayInt *cellIds1D=0;
3746   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3747   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3748   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3749   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3750   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3752   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3753   revDesc2=0; revDescIndx2=0;
3754   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3755   revDesc1=0; revDescIndx1=0;
3756   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3757   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3758   //
3759   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3760   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3761     cut3DCurve[*it]=-1;
3762   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3763   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3764   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3765                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3766                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3767   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3768   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3769   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3770   if(cellIds2->empty())
3771     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3772   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3773   ret->setCoords(mDesc1->getCoords());
3774   ret->setConnectivity(conn,connI,true);
3775   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3776   return ret.retn();
3777 }
3778
3779 /*!
3780  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3781 addition to the mesh, returns a new DataArrayInt, of length equal to the number of 1D cells in the result mesh, holding, for each cell in the result mesh, an id of a 2D cell it comes
3782 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3783 the result mesh.
3784  *  \param [in] origin - 3 components of a point defining location of the plane.
3785  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3786  *         must be greater than 1e-6.
3787  *  \param [in] eps - half-thickness of the plane.
3788  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3789  *         producing correspondent segments. The caller is to delete this array
3790  *         using decrRef() as it is no more needed.
3791  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3792  *         mesh in 3D space. This mesh does not share the node coordinates array with
3793  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3794  *         no more needed. 
3795  *  \throw If the coordinates array is not set.
3796  *  \throw If the nodal connectivity of cells is not defined.
3797  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3798  *  \throw If magnitude of \a vec is less than 1e-6.
3799  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3800  *  \throw If \a this includes quadratic cells.
3801  */
3802 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3803 {
3804   checkFullyDefined();
3805   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3806     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3807   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3808   if(candidates->empty())
3809     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3810   std::vector<int> nodes;
3811   DataArrayInt *cellIds1D=0;
3812   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3813   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3814   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3815   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3816   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3817   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3818   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3819   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3821   //
3822   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3823   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3824     cut3DCurve[*it]=-1;
3825   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3826   int ncellsSub=subMesh->getNumberOfCells();
3827   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3828   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3829                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3830                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3831   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3832   conn->alloc(0,1);
3833   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3834   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3835   for(int i=0;i<ncellsSub;i++)
3836     {
3837       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3838         {
3839           if(cut3DSurf[i].first!=-2)
3840             {
3841               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3842               connI->pushBackSilent(conn->getNumberOfTuples());
3843               cellIds2->pushBackSilent(i);
3844             }
3845           else
3846             {
3847               int cellId3DSurf=cut3DSurf[i].second;
3848               int offset=nodalI[cellId3DSurf]+1;
3849               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3850               for(int j=0;j<nbOfEdges;j++)
3851                 {
3852                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3853                   connI->pushBackSilent(conn->getNumberOfTuples());
3854                   cellIds2->pushBackSilent(cellId3DSurf);
3855                 }
3856             }
3857         }
3858     }
3859   if(cellIds2->empty())
3860     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3861   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3862   ret->setCoords(mDesc1->getCoords());
3863   ret->setConnectivity(conn,connI,true);
3864   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3865   return ret.retn();
3866 }
3867
3868 /*!
3869  * Finds cells whose bounding boxes intersect a given plane.
3870  *  \param [in] origin - 3 components of a point defining location of the plane.
3871  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3872  *         must be greater than 1e-6.
3873  *  \param [in] eps - half-thickness of the plane.
3874  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3875  *         cells. The caller is to delete this array using decrRef() as it is no more
3876  *         needed.
3877  *  \throw If the coordinates array is not set.
3878  *  \throw If the nodal connectivity of cells is not defined.
3879  *  \throw If \a this->getSpaceDimension() != 3.
3880  *  \throw If magnitude of \a vec is less than 1e-6.
3881  *  \sa buildSlice3D()
3882  */
3883 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3884 {
3885   checkFullyDefined();
3886   if(getSpaceDimension()!=3)
3887     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3888   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3889   if(normm<1e-6)
3890     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3891   double vec2[3];
3892   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3893   double angle=acos(vec[2]/normm);
3894   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3895   double bbox[6];
3896   if(angle>eps)
3897     {
3898       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3899       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
4247
4248   /*!
4249    * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4250    */
4251   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4252   {
4253     INTERP_KERNEL::Edge *ret(0);
4254     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]));
4255     m[n0]=bg[0]; m[n1]=bg[1];
4256     switch(typ)
4257     {
4258       case INTERP_KERNEL::NORM_SEG2:
4259         {
4260           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4261           break;
4262         }
4263       case INTERP_KERNEL::NORM_SEG3:
4264         {
4265           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4266           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4267           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4268           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4269           bool colinearity(inters.areColinears());
4270           delete e1; delete e2;
4271           if(colinearity)
4272             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4273           else
4274             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4275           break;
4276         }
4277       default:
4278         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4279     }
4280     return ret;
4281   }
4282
4283   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4284   {
4285     INTERP_KERNEL::Edge *ret=0;
4286     switch(typ)
4287     {
4288       case INTERP_KERNEL::NORM_SEG2:
4289         {
4290           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4291           break;
4292         }
4293       case INTERP_KERNEL::NORM_SEG3:
4294         {
4295           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4296           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4297           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4298           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4299           bool colinearity=inters.areColinears();
4300           delete e1; delete e2;
4301           if(colinearity)
4302             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4303           else
4304             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4305           mapp2[bg[2]].second=false;
4306           break;
4307         }
4308       default:
4309         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4310     }
4311     return ret;
4312   }
4313
4314   /*!
4315    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4316    * the global mesh 'mDesc'.
4317    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4318    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4319    */
4320   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4321                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4322   {
4323     mapp.clear();
4324     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.
4325     const double *coo=mDesc->getCoords()->getConstPointer();
4326     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4327     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4328     std::set<int> s;
4329     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4330       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4331     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4332       {
4333         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4334         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4335       }
4336     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4337     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4338       {
4339         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4340         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4341       }
4342     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4343       {
4344         if((*it2).second.second)
4345           mapp[(*it2).second.first]=(*it2).first;
4346         ((*it2).second.first)->decrRef();
4347       }
4348     return ret;
4349   }
4350
4351   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4352   {
4353     if(nodeId>=offset2)
4354       {
4355         int locId=nodeId-offset2;
4356         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4357       }
4358     if(nodeId>=offset1)
4359       {
4360         int locId=nodeId-offset1;
4361         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4362       }
4363     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4364   }
4365
4366   /**
4367    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4368    */
4369   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4370                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4371                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4372   {
4373     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4374       {
4375         int eltId1=abs(*desc1)-1;
4376         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4377           {
4378             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4379             if(it==mappRev.end())
4380               {
4381                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4382                 mapp[node]=*it1;
4383                 mappRev[*it1]=node;
4384               }
4385           }
4386       }
4387   }
4388 }
4389
4390 /// @endcond
4391
4392 template<int SPACEDIM>
4393 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4394                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4395 {
4396   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4397   int *eltsIndexPtr(eltsIndex->getPointer());
4398   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4399   const double *bbox(bboxArr->begin());
4400   int nbOfCells=getNumberOfCells();
4401   const int *conn=_nodal_connec->getConstPointer();
4402   const int *connI=_nodal_connec_index->getConstPointer();
4403   double bb[2*SPACEDIM];
4404   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4405   for(int i=0;i<nbOfPoints;i++)
4406     {
4407       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4408       for(int j=0;j<SPACEDIM;j++)
4409         {
4410           bb[2*j]=pos[SPACEDIM*i+j];
4411           bb[2*j+1]=pos[SPACEDIM*i+j];
4412         }
4413       std::vector<int> candidates;
4414       myTree.getIntersectingElems(bb,candidates);
4415       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4416         {
4417           int sz(connI[(*iter)+1]-connI[*iter]-1);
4418           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4419           bool status(false);
4420           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4421             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4422           else
4423             {
4424               if(SPACEDIM!=2)
4425                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4426               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4427               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4428               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4429               INTERP_KERNEL::QuadraticPolygon *pol(0);
4430               for(int j=0;j<sz;j++)
4431                 {
4432                   int nodeId(conn[connI[*iter]+1+j]);
4433                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4434                 }
4435               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4436                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4437               else
4438                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4439               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4440               double a(0.),b(0.),c(0.);
4441               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4442               status=pol->isInOrOut2(n);
4443               delete pol; n->decrRef();
4444             }
4445           if(status)
4446             {
4447               eltsIndexPtr[i+1]++;
4448               elts->pushBackSilent(*iter);
4449             }
4450         }
4451     }
4452 }
4453 /*!
4454  * Finds cells in contact with several balls (i.e. points with precision).
4455  * This method is an extension of getCellContainingPoint() and
4456  * getCellsContainingPoint() for the case of multiple points.
4457  * 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.
4458  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4459  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4460  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4461  *         this->getSpaceDimension() * \a nbOfPoints 
4462  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4463  *  \param [in] eps - radius of balls (i.e. the precision).
4464  *  \param [out] elts - vector returning ids of found cells.
4465  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4466  *         dividing cell ids in \a elts into groups each referring to one
4467  *         point. Its every element (except the last one) is an index pointing to the
4468  *         first id of a group of cells. For example cells in contact with the *i*-th
4469  *         point are described by following range of indices:
4470  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4471  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4472  *         Number of cells in contact with the *i*-th point is
4473  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4474  *  \throw If the coordinates array is not set.
4475  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4476  *
4477  *  \if ENABLE_EXAMPLES
4478  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4479  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4480  *  \endif
4481  */
4482 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4483                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4484 {
4485   int spaceDim=getSpaceDimension();
4486   int mDim=getMeshDimension();
4487   if(spaceDim==3)
4488     {
4489       if(mDim==3)
4490         {
4491           const double *coords=_coords->getConstPointer();
4492           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4493         }
4494       /*else if(mDim==2)
4495         {
4496
4497         }*/
4498       else
4499         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4500     }
4501   else if(spaceDim==2)
4502     {
4503       if(mDim==2)
4504         {
4505           const double *coords=_coords->getConstPointer();
4506           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4507         }
4508       else
4509         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4510     }
4511   else if(spaceDim==1)
4512     {
4513       if(mDim==1)
4514         {
4515           const double *coords=_coords->getConstPointer();
4516           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4517         }
4518       else
4519         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4520     }
4521   else
4522     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4523 }
4524
4525 /*!
4526  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4527  * least two its edges intersect each other anywhere except their extremities. An
4528  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4529  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4530  *         cleared before filling in.
4531  *  \param [in] eps - precision.
4532  *  \throw If \a this->getMeshDimension() != 2.
4533  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4534  */
4535 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4536 {
4537   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4538   if(getMeshDimension()!=2)
4539     throw INTERP_KERNEL::Exception(msg);
4540   int spaceDim=getSpaceDimension();
4541   if(spaceDim!=2 && spaceDim!=3)
4542     throw INTERP_KERNEL::Exception(msg);
4543   const int *conn=_nodal_connec->getConstPointer();
4544   const int *connI=_nodal_connec_index->getConstPointer();
4545   int nbOfCells=getNumberOfCells();
4546   std::vector<double> cell2DinS2;
4547   for(int i=0;i<nbOfCells;i++)
4548     {
4549       int offset=connI[i];
4550       int nbOfNodesForCell=connI[i+1]-offset-1;
4551       if(nbOfNodesForCell<=3)
4552         continue;
4553       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4554       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4555       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4556         cells.push_back(i);
4557       cell2DinS2.clear();
4558     }
4559 }
4560
4561 /*!
4562  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4563  *
4564  * 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.
4565  * 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.
4566  * 
4567  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4568  * This convex envelop is computed using Jarvis march algorithm.
4569  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4570  * 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)
4571  * 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.
4572  *
4573  * \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.
4574  * \sa MEDCouplingUMesh::colinearize2D
4575  */
4576 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4577 {
4578   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4579     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4580   checkFullyDefined();
4581   const double *coords=getCoords()->getConstPointer();
4582   int nbOfCells=getNumberOfCells();
4583   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4584   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4585   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4586   int *workIndexOut=nodalConnecIndexOut->getPointer();
4587   *workIndexOut=0;
4588   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4589   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4590   std::set<INTERP_KERNEL::NormalizedCellType> types;
4591   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4592   isChanged->alloc(0,1);
4593   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4594     {
4595       int pos=nodalConnecOut->getNumberOfTuples();
4596       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4597         isChanged->pushBackSilent(i);
4598       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4599       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4600     }
4601   if(isChanged->empty())
4602     return 0;
4603   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4604   _types=types;
4605   return isChanged.retn();
4606 }
4607
4608 /*!
4609  * This method is \b NOT const because it can modify \a this.
4610  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4611  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4612  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4613  * \b 1 for translation and rotation around point of 'mesh1D'.
4614  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4615  */
4616 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4617 {
4618   checkFullyDefined();
4619   mesh1D->checkFullyDefined();
4620   if(!mesh1D->isContiguous1D())
4621     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4622   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4623     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4624   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4625     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4626   if(mesh1D->getMeshDimension()!=1)
4627     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4628   bool isQuad=false;
4629   if(isPresenceOfQuadratic())
4630     {
4631       if(mesh1D->isFullyQuadratic())
4632         isQuad=true;
4633       else
4634         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4635     }
4636   zipCoords();
4637   int oldNbOfNodes=getNumberOfNodes();
4638   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4639   switch(policy)
4640   {
4641     case 0:
4642       {
4643         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4644         break;
4645       }
4646     case 1:
4647       {
4648         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4649         break;
4650       }
4651     default:
4652       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4653   }
4654   setCoords(newCoords);
4655   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4656   updateTime();
4657   return ret.retn();
4658 }
4659
4660 /*!
4661  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4662  * If it is not the case an exception will be thrown.
4663  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4664  * intersection of plane defined by ('origin','vec').
4665  * This method has one in/out parameter : 'cut3DCurve'.
4666  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4667  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4668  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4669  * This method will throw an exception if \a this contains a non linear segment.
4670  */
4671 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4672 {
4673   checkFullyDefined();
4674   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4675     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4676   int ncells=getNumberOfCells();
4677   int nnodes=getNumberOfNodes();
4678   double vec2[3],vec3[3],vec4[3];
4679   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4680   if(normm<1e-6)
4681     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4682   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4683   const int *conn=_nodal_connec->getConstPointer();
4684   const int *connI=_nodal_connec_index->getConstPointer();
4685   const double *coo=_coords->getConstPointer();
4686   std::vector<double> addCoo;
4687   for(int i=0;i<ncells;i++)
4688     {
4689       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4690         {
4691           if(cut3DCurve[i]==-2)
4692             {
4693               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4694               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];
4695               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4696               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4697               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4698                 {
4699                   const double *st2=coo+3*st;
4700                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4701                   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]));
4702                   if(pos>eps && pos<1-eps)
4703                     {
4704                       int nNode=((int)addCoo.size())/3;
4705                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4706                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4707                       cut3DCurve[i]=nnodes+nNode;
4708                     }
4709                 }
4710             }
4711         }
4712       else
4713         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4714     }
4715   if(!addCoo.empty())
4716     {
4717       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4718       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4719       coo2->alloc(newNbOfNodes,3);
4720       double *tmp=coo2->getPointer();
4721       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4722       std::copy(addCoo.begin(),addCoo.end(),tmp);
4723       DataArrayDouble::SetArrayIn(coo2,_coords);
4724     }
4725 }
4726
4727 /*!
4728  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4729  * \param mesh1D is the input 1D mesh used for translation computation.
4730  * \return newCoords new coords filled by this method. 
4731  */
4732 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4733 {
4734   int oldNbOfNodes=getNumberOfNodes();
4735   int nbOf1DCells=mesh1D->getNumberOfCells();
4736   int spaceDim=getSpaceDimension();
4737   DataArrayDouble *ret=DataArrayDouble::New();
4738   std::vector<bool> isQuads;
4739   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4740   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4741   double *retPtr=ret->getPointer();
4742   const double *coords=getCoords()->getConstPointer();
4743   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4744   std::vector<int> v;
4745   std::vector<double> c;
4746   double vec[3];
4747   v.reserve(3);
4748   c.reserve(6);
4749   for(int i=0;i<nbOf1DCells;i++)
4750     {
4751       v.resize(0);
4752       mesh1D->getNodeIdsOfCell(i,v);
4753       c.resize(0);
4754       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4755       mesh1D->getCoordinatesOfNode(v[0],c);
4756       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4757       for(int j=0;j<oldNbOfNodes;j++)
4758         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4759       if(isQuad)
4760         {
4761           c.resize(0);
4762           mesh1D->getCoordinatesOfNode(v[1],c);
4763           mesh1D->getCoordinatesOfNode(v[0],c);
4764           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4765           for(int j=0;j<oldNbOfNodes;j++)
4766             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4767         }
4768     }
4769   ret->copyStringInfoFrom(*getCoords());
4770   return ret;
4771 }
4772
4773 /*!
4774  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4775  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4776  * \return newCoords new coords filled by this method. 
4777  */
4778 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4779 {
4780   if(mesh1D->getSpaceDimension()==2)
4781     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4782   if(mesh1D->getSpaceDimension()==3)
4783     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4784   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4785 }
4786
4787 /*!
4788  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4789  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4790  * \return newCoords new coords filled by this method. 
4791  */
4792 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4793 {
4794   if(isQuad)
4795     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4796   int oldNbOfNodes=getNumberOfNodes();
4797   int nbOf1DCells=mesh1D->getNumberOfCells();
4798   if(nbOf1DCells<2)
4799     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4800   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4801   int nbOfLevsInVec=nbOf1DCells+1;
4802   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4803   double *retPtr=ret->getPointer();
4804   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4805   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4806   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4807   tmp->setCoords(tmp2);
4808   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4809   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4810   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4811   for(int i=1;i<nbOfLevsInVec;i++)
4812     {
4813       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4814       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4815       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4816       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4817       tmp->translate(vec);
4818       double tmp3[2],radius,alpha,alpha0;
4819       const double *p0=i+1<nbOfLevsInVec?begin:third;
4820       const double *p1=i+1<nbOfLevsInVec?end:begin;
4821       const double *p2=i+1<nbOfLevsInVec?third:end;
4822       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4823       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]);
4824       double angle=acos(cosangle/(radius*radius));
4825       tmp->rotate(end,0,angle);
4826       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4827     }
4828   return ret.retn();
4829 }
4830
4831 /*!
4832  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4833  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4834  * \return newCoords new coords filled by this method. 
4835  */
4836 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4837 {
4838   if(isQuad)
4839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4840   int oldNbOfNodes=getNumberOfNodes();
4841   int nbOf1DCells=mesh1D->getNumberOfCells();
4842   if(nbOf1DCells<2)
4843     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4844   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4845   int nbOfLevsInVec=nbOf1DCells+1;
4846   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4847   double *retPtr=ret->getPointer();
4848   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4849   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4850   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4851   tmp->setCoords(tmp2);
4852   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4853   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4854   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4855   for(int i=1;i<nbOfLevsInVec;i++)
4856     {
4857       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4858       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4859       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4860       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4861       tmp->translate(vec);
4862       double tmp3[2],radius,alpha,alpha0;
4863       const double *p0=i+1<nbOfLevsInVec?begin:third;
4864       const double *p1=i+1<nbOfLevsInVec?end:begin;
4865       const double *p2=i+1<nbOfLevsInVec?third:end;
4866       double vecPlane[3]={
4867         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4868         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4869         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4870       };
4871       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4872       if(norm>1.e-7)
4873         {
4874           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4875           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4876           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4877           double s2=norm2;
4878           double c2=cos(asin(s2));
4879           double m[3][3]={
4880             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4881             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4882             {-vec2[1]*s2, vec2[0]*s2, c2}
4883           };
4884           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]};
4885           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]};
4886           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]};
4887           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4888           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]);
4889           double angle=acos(cosangle/(radius*radius));
4890           tmp->rotate(end,vecPlane,angle);
4891         }
4892       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4893     }
4894   return ret.retn();
4895 }
4896
4897 /*!
4898  * This method is private because not easy to use for end user. This method is const contrary to
4899  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4900  * the coords sorted slice by slice.
4901  * \param isQuad specifies presence of quadratic cells.
4902  */
4903 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4904 {
4905   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4906   int nbOf2DCells=getNumberOfCells();
4907   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4908   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4909   const int *conn=_nodal_connec->getConstPointer();
4910   const int *connI=_nodal_connec_index->getConstPointer();
4911   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4912   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4913   newConnI->alloc(nbOf3DCells+1,1);
4914   int *newConnIPtr=newConnI->getPointer();
4915   *newConnIPtr++=0;
4916   std::vector<int> newc;
4917   for(int j=0;j<nbOf2DCells;j++)
4918     {
4919       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4920       *newConnIPtr++=(int)newc.size();
4921     }
4922   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4923   int *newConnPtr=newConn->getPointer();
4924   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4925   newConnIPtr=newConnI->getPointer();
4926   for(int iz=0;iz<nbOf1DCells;iz++)
4927     {
4928       if(iz!=0)
4929         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4930       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4931         {
4932           int icell=(int)(iter-newc.begin());
4933           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4934             {
4935               if(*iter!=-1)
4936                 *newConnPtr=(*iter)+iz*deltaPerLev;
4937               else
4938                 *newConnPtr=-1;
4939             }
4940           else
4941             *newConnPtr=(*iter);
4942         }
4943     }
4944   ret->setConnectivity(newConn,newConnI,true);
4945   ret->setCoords(getCoords());
4946   return ret;
4947 }
4948
4949 /*!
4950  * Checks if \a this mesh is constituted by only quadratic cells.
4951  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4952  *  \throw If the coordinates array is not set.
4953  *  \throw If the nodal connectivity of cells is not defined.
4954  */
4955 bool MEDCouplingUMesh::isFullyQuadratic() const
4956 {
4957   checkFullyDefined();
4958   bool ret=true;
4959   int nbOfCells=getNumberOfCells();
4960   for(int i=0;i<nbOfCells && ret;i++)
4961     {
4962       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4963       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4964       ret=cm.isQuadratic();
4965     }
4966   return ret;
4967 }
4968
4969 /*!
4970  * Checks if \a this mesh includes any quadratic cell.
4971  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4972  *  \throw If the coordinates array is not set.
4973  *  \throw If the nodal connectivity of cells is not defined.
4974  */
4975 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4976 {
4977   checkFullyDefined();
4978   bool ret=false;
4979   int nbOfCells=getNumberOfCells();
4980   for(int i=0;i<nbOfCells && !ret;i++)
4981     {
4982       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4983       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4984       ret=cm.isQuadratic();
4985     }
4986   return ret;
4987 }
4988
4989 /*!
4990  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4991  * this mesh, it remains unchanged.
4992  *  \throw If the coordinates array is not set.
4993  *  \throw If the nodal connectivity of cells is not defined.
4994  */
4995 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4996 {
4997   checkFullyDefined();
4998   int nbOfCells=getNumberOfCells();
4999   int delta=0;
5000   const int *iciptr=_nodal_connec_index->getConstPointer();
5001   for(int i=0;i<nbOfCells;i++)
5002     {
5003       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5004       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5005       if(cm.isQuadratic())
5006         {
5007           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5008           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5009           if(!cml.isDynamic())
5010             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5011           else
5012             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5013         }
5014     }
5015   if(delta==0)
5016     return ;
5017   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5018   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5019   const int *icptr=_nodal_connec->getConstPointer();
5020   newConn->alloc(getMeshLength()-delta,1);
5021   newConnI->alloc(nbOfCells+1,1);
5022   int *ocptr=newConn->getPointer();
5023   int *ociptr=newConnI->getPointer();
5024   *ociptr=0;
5025   _types.clear();
5026   for(int i=0;i<nbOfCells;i++,ociptr++)
5027     {
5028       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5029       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5030       if(!cm.isQuadratic())
5031         {
5032           _types.insert(type);
5033           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5034           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5035         }
5036       else
5037         {
5038           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5039           _types.insert(typel);
5040           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5041           int newNbOfNodes=cml.getNumberOfNodes();
5042           if(cml.isDynamic())
5043             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5044           *ocptr++=(int)typel;
5045           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5046           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5047         }
5048     }
5049   setConnectivity(newConn,newConnI,false);
5050 }
5051
5052 /*!
5053  * This method converts all linear cell in \a this to quadratic one.
5054  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5055  * 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)
5056  * 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.
5057  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5058  * end of the existing coordinates.
5059  * 
5060  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5061  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5062  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5063  * 
5064  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5065  *
5066  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5067  */
5068 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5069 {
5070   DataArrayInt *conn=0,*connI=0;
5071   DataArrayDouble *coords=0;
5072   std::set<INTERP_KERNEL::NormalizedCellType> types;
5073   checkFullyDefined();
5074   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5075   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5076   int meshDim=getMeshDimension();
5077   switch(conversionType)
5078   {
5079     case 0:
5080       switch(meshDim)
5081       {
5082         case 1:
5083           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5084           connSafe=conn; connISafe=connI; coordsSafe=coords;
5085           break;
5086         case 2:
5087           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5088           connSafe=conn; connISafe=connI; coordsSafe=coords;
5089           break;
5090         case 3:
5091           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5092           connSafe=conn; connISafe=connI; coordsSafe=coords;
5093           break;
5094         default:
5095           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5096       }
5097       break;
5098         case 1:
5099           {
5100             switch(meshDim)
5101             {
5102               case 1:
5103                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5104                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5105                 break;
5106               case 2:
5107                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5108                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5109                 break;
5110               case 3:
5111                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5112                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5113                 break;
5114               default:
5115                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5116             }
5117             break;
5118           }
5119         default:
5120           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5121   }
5122   setConnectivity(connSafe,connISafe,false);
5123   _types=types;
5124   setCoords(coordsSafe);
5125   return ret.retn();
5126 }
5127
5128 #if 0
5129 /*!
5130  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5131  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5132  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5133  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5134  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5135  * This method can be seen as the opposite method of colinearize2D.
5136  * 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
5137  * to avoid to modify the numbering of existing nodes.
5138  *
5139  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5140  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5141  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5142  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5143  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5144  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5145  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5146  *
5147  * \sa buildDescendingConnectivity2
5148  */
5149 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5150                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5151 {
5152   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5153     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5154   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5155   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5156     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5157   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5158     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5159   //DataArrayInt *out0(0),*outi0(0);
5160   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5161   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5162   //out0s=out0s->buildUnique(); out0s->sort(true);
5163 }
5164 #endif
5165
5166 /*!
5167  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5168  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5169  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5170  */
5171 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5172 {
5173   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5174   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5175   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5176   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5177   int nbOfCells=getNumberOfCells();
5178   int nbOfNodes=getNumberOfNodes();
5179   const int *cPtr=_nodal_connec->getConstPointer();
5180   const int *icPtr=_nodal_connec_index->getConstPointer();
5181   int lastVal=0,offset=nbOfNodes;
5182   for(int i=0;i<nbOfCells;i++,icPtr++)
5183     {
5184       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5185       if(type==INTERP_KERNEL::NORM_SEG2)
5186         {
5187           types.insert(INTERP_KERNEL::NORM_SEG3);
5188           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5189           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5190           newConn->pushBackSilent(offset++);
5191           lastVal+=4;
5192           newConnI->pushBackSilent(lastVal);
5193           ret->pushBackSilent(i);
5194         }
5195       else
5196         {
5197           types.insert(type);
5198           lastVal+=(icPtr[1]-icPtr[0]);
5199           newConnI->pushBackSilent(lastVal);
5200           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5201         }
5202     }
5203   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5204   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5205   return ret.retn();
5206 }
5207
5208 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
5209 {
5210   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5212   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5213   //
5214   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5215   DataArrayInt *conn1D=0,*conn1DI=0;
5216   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5217   DataArrayDouble *coordsTmp=0;
5218   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5219   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5220   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5221   const int *c1DPtr=conn1D->begin();
5222   const int *c1DIPtr=conn1DI->begin();
5223   int nbOfCells=getNumberOfCells();
5224   const int *cPtr=_nodal_connec->getConstPointer();
5225   const int *icPtr=_nodal_connec_index->getConstPointer();
5226   int lastVal=0;
5227   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5228     {
5229       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5231       if(!cm.isQuadratic())
5232         {
5233           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5234           types.insert(typ2); newConn->pushBackSilent(typ2);
5235           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5236           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5237             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5238           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5239           newConnI->pushBackSilent(lastVal);
5240           ret->pushBackSilent(i);
5241         }
5242       else
5243         {
5244           types.insert(typ);
5245           lastVal+=(icPtr[1]-icPtr[0]);
5246           newConnI->pushBackSilent(lastVal);
5247           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5248         }
5249     }
5250   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5251   return ret.retn();
5252 }
5253
5254 /*!
5255  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5256  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5257  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5258  */
5259 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5260 {
5261   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5262   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5263   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5264 }
5265
5266 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5267 {
5268   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5269   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5270   //
5271   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5273   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5274   //
5275   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5276   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5277   DataArrayInt *conn1D=0,*conn1DI=0;
5278   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5279   DataArrayDouble *coordsTmp=0;
5280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5281   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5282   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5283   const int *c1DPtr=conn1D->begin();
5284   const int *c1DIPtr=conn1DI->begin();
5285   int nbOfCells=getNumberOfCells();
5286   const int *cPtr=_nodal_connec->getConstPointer();
5287   const int *icPtr=_nodal_connec_index->getConstPointer();
5288   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5289   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5290     {
5291       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5292       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5293       if(!cm.isQuadratic())
5294         {
5295           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5296           types.insert(typ2); newConn->pushBackSilent(typ2);
5297           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5298           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5299             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5300           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5301           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5302           newConnI->pushBackSilent(lastVal);
5303           ret->pushBackSilent(i);
5304         }
5305       else
5306         {
5307           types.insert(typ);
5308           lastVal+=(icPtr[1]-icPtr[0]);
5309           newConnI->pushBackSilent(lastVal);
5310           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5311         }
5312     }
5313   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5314   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5315   return ret.retn();
5316 }
5317
5318 /*!
5319  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5320  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5321  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5322  */
5323 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5324 {
5325   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5326   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5327   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5328 }
5329
5330 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5331 {
5332   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5333   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5334   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5335   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5336   //
5337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5339   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5340   //
5341   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5342   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5343   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5344   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5345   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5348   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5349   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5350   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5351   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5352   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5353   int nbOfCells=getNumberOfCells();
5354   const int *cPtr=_nodal_connec->getConstPointer();
5355   const int *icPtr=_nodal_connec_index->getConstPointer();
5356   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5357   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5358     {
5359       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5360       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5361       if(!cm.isQuadratic())
5362         {
5363           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5364           if(typ2==INTERP_KERNEL::NORM_ERROR)
5365             {
5366               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5367               throw INTERP_KERNEL::Exception(oss.str().c_str());
5368             }
5369           types.insert(typ2); newConn->pushBackSilent(typ2);
5370           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5371           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5372             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5373           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5374             {
5375               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5376               int tmpPos=newConn->getNumberOfTuples();
5377               newConn->pushBackSilent(nodeId2);
5378               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5379             }
5380           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5381           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5382           newConnI->pushBackSilent(lastVal);
5383           ret->pushBackSilent(i);
5384         }
5385       else
5386         {
5387           types.insert(typ);
5388           lastVal+=(icPtr[1]-icPtr[0]);
5389           newConnI->pushBackSilent(lastVal);
5390           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5391         }
5392     }
5393   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5394   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5395   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5396   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5397   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5398   int *c=newConn->getPointer();
5399   const int *cI(newConnI->begin());
5400   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5401     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5402   offset=coordsTmp2Safe->getNumberOfTuples();
5403   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5404     c[cI[(*elt)+1]-1]+=offset;
5405   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5406   return ret.retn();
5407 }
5408
5409 /*!
5410  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5411  * so that the number of cells remains the same. Quadratic faces are converted to
5412  * polygons. This method works only for 2D meshes in
5413  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5414  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5415  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5416  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5417  *         a polylinized edge constituting the input polygon.
5418  *  \throw If the coordinates array is not set.
5419  *  \throw If the nodal connectivity of cells is not defined.
5420  *  \throw If \a this->getMeshDimension() != 2.
5421  *  \throw If \a this->getSpaceDimension() != 2.
5422  */
5423 void MEDCouplingUMesh::tessellate2D(double eps)
5424 {
5425   checkFullyDefined();
5426   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5427     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5428   double epsa=fabs(eps);
5429   if(epsa<std::numeric_limits<double>::min())
5430     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 !");
5431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5433   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5434   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5435   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5436   revDesc1=0; revDescIndx1=0;
5437   mDesc->tessellate2DCurve(eps);
5438   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5439   setCoords(mDesc->getCoords());
5440 }
5441
5442 /*!
5443  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5444  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5445  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5446  *         a sub-divided edge.
5447  *  \throw If the coordinates array is not set.
5448  *  \throw If the nodal connectivity of cells is not defined.
5449  *  \throw If \a this->getMeshDimension() != 1.
5450  *  \throw If \a this->getSpaceDimension() != 2.
5451  */
5452 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5453 {
5454   checkFullyDefined();
5455   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5456     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5457   double epsa=fabs(eps);
5458   if(epsa<std::numeric_limits<double>::min())
5459     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 !");
5460   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5461   int nbCells=getNumberOfCells();
5462   int nbNodes=getNumberOfNodes();
5463   const int *conn=_nodal_connec->getConstPointer();
5464   const int *connI=_nodal_connec_index->getConstPointer();
5465   const double *coords=_coords->getConstPointer();
5466   std::vector<double> addCoo;
5467   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5468   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5469   newConnI->alloc(nbCells+1,1);
5470   int *newConnIPtr=newConnI->getPointer();
5471   *newConnIPtr=0;
5472   int tmp1[3];
5473   INTERP_KERNEL::Node *tmp2[3];
5474   std::set<INTERP_KERNEL::NormalizedCellType> types;
5475   for(int i=0;i<nbCells;i++,newConnIPtr++)
5476     {
5477       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5478       if(cm.isQuadratic())
5479         {//assert(connI[i+1]-connI[i]-1==3)
5480           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5481           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5482           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5483           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5484           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5485           if(eac)
5486             {
5487               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5488               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5489               delete eac;
5490               newConnIPtr[1]=(int)newConn.size();
5491             }
5492           else
5493             {
5494               types.insert(INTERP_KERNEL::NORM_SEG2);
5495               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5496               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5497               newConnIPtr[1]=newConnIPtr[0]+3;
5498             }
5499         }
5500       else
5501         {
5502           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5503           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5504           newConnIPtr[1]=newConnIPtr[0]+3;
5505         }
5506     }
5507   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5508     return ;
5509   _types=types;
5510   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5511   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5512   newConnArr->alloc((int)newConn.size(),1);
5513   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5514   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5515   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5516   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5517   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5518   std::copy(addCoo.begin(),addCoo.end(),work);
5519   DataArrayDouble::SetArrayIn(newCoords,_coords);
5520   updateTime();
5521 }
5522
5523 /*!
5524  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5525  * In addition, returns an array mapping new cells to old ones. <br>
5526  * This method typically increases the number of cells in \a this mesh
5527  * but the number of nodes remains \b unchanged.
5528  * That's why the 3D splitting policies
5529  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5530  *  \param [in] policy - specifies a pattern used for splitting.
5531  * The semantic of \a policy is:
5532  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5533  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5534  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5535  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5536  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5537  *          an id of old cell producing it. The caller is to delete this array using
5538  *         decrRef() as it is no more needed. 
5539  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5540  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5541  *          and \a this->getMeshDimension() != 3. 
5542  *  \throw If \a policy is not one of the four discussed above.
5543  *  \throw If the nodal connectivity of cells is not defined.
5544  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5545  */
5546 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5547 {
5548   switch(policy)
5549   {
5550     case 0:
5551       return simplexizePol0();
5552     case 1:
5553       return simplexizePol1();
5554     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5555         return simplexizePlanarFace5();
5556     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5557         return simplexizePlanarFace6();
5558     default:
5559       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)");
5560   }
5561 }
5562
5563 /*!
5564  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5565  * - 1D: INTERP_KERNEL::NORM_SEG2
5566  * - 2D: INTERP_KERNEL::NORM_TRI3
5567  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5568  *
5569  * This method is useful for users that need to use P1 field services as
5570  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5571  * All these methods need mesh support containing only simplex cells.
5572  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5573  *  \throw If the coordinates array is not set.
5574  *  \throw If the nodal connectivity of cells is not defined.
5575  *  \throw If \a this->getMeshDimension() < 1.
5576  */
5577 bool MEDCouplingUMesh::areOnlySimplexCells() const
5578 {
5579   checkFullyDefined();
5580   int mdim=getMeshDimension();
5581   if(mdim<1 || mdim>3)
5582     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5583   int nbCells=getNumberOfCells();
5584   const int *conn=_nodal_connec->getConstPointer();
5585   const int *connI=_nodal_connec_index->getConstPointer();
5586   for(int i=0;i<nbCells;i++)
5587     {
5588       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5589       if(!cm.isSimplex())
5590         return false;
5591     }
5592   return true;
5593 }
5594
5595 /*!
5596  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5597  */
5598 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5599 {
5600   checkConnectivityFullyDefined();
5601   if(getMeshDimension()!=2)
5602     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5603   int nbOfCells=getNumberOfCells();
5604   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5605   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5606   ret->alloc(nbOfCells+nbOfCutCells,1);
5607   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5608   int *retPt=ret->getPointer();
5609   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5610   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5611   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5612   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5613   int *pt=newConn->getPointer();
5614   int *ptI=newConnI->getPointer();
5615   ptI[0]=0;
5616   const int *oldc=_nodal_connec->getConstPointer();
5617   const int *ci=_nodal_connec_index->getConstPointer();
5618   for(int i=0;i<nbOfCells;i++,ci++)
5619     {
5620       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5621         {
5622           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5623             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5624           pt=std::copy(tmp,tmp+8,pt);
5625           ptI[1]=ptI[0]+4;
5626           ptI[2]=ptI[0]+8;
5627           *retPt++=i;
5628           *retPt++=i;
5629           ptI+=2;
5630         }
5631       else
5632         {
5633           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5634           ptI[1]=ptI[0]+ci[1]-ci[0];
5635           ptI++;
5636           *retPt++=i;
5637         }
5638     }
5639   _nodal_connec->decrRef();
5640   _nodal_connec=newConn.retn();
5641   _nodal_connec_index->decrRef();
5642   _nodal_connec_index=newConnI.retn();
5643   computeTypes();
5644   updateTime();
5645   return ret.retn();
5646 }
5647
5648 /*!
5649  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5650  */
5651 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5652 {
5653   checkConnectivityFullyDefined();
5654   if(getMeshDimension()!=2)
5655     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5656   int nbOfCells=getNumberOfCells();
5657   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5658   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5659   ret->alloc(nbOfCells+nbOfCutCells,1);
5660   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5661   int *retPt=ret->getPointer();
5662   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5663   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5664   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5665   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5666   int *pt=newConn->getPointer();
5667   int *ptI=newConnI->getPointer();
5668   ptI[0]=0;
5669   const int *oldc=_nodal_connec->getConstPointer();
5670   const int *ci=_nodal_connec_index->getConstPointer();
5671   for(int i=0;i<nbOfCells;i++,ci++)
5672     {
5673       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5674         {
5675           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5676             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5677           pt=std::copy(tmp,tmp+8,pt);
5678           ptI[1]=ptI[0]+4;
5679           ptI[2]=ptI[0]+8;
5680           *retPt++=i;
5681           *retPt++=i;
5682           ptI+=2;
5683         }
5684       else
5685         {
5686           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5687           ptI[1]=ptI[0]+ci[1]-ci[0];
5688           ptI++;
5689           *retPt++=i;
5690         }
5691     }
5692   _nodal_connec->decrRef();
5693   _nodal_connec=newConn.retn();
5694   _nodal_connec_index->decrRef();
5695   _nodal_connec_index=newConnI.retn();
5696   computeTypes();
5697   updateTime();
5698   return ret.retn();
5699 }
5700
5701 /*!
5702  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5703  */
5704 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5705 {
5706   checkConnectivityFullyDefined();
5707   if(getMeshDimension()!=3)
5708     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5709   int nbOfCells=getNumberOfCells();
5710   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5711   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5712   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5713   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5714   int *retPt=ret->getPointer();
5715   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5716   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5717   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5718   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5719   int *pt=newConn->getPointer();
5720   int *ptI=newConnI->getPointer();
5721   ptI[0]=0;
5722   const int *oldc=_nodal_connec->getConstPointer();
5723   const int *ci=_nodal_connec_index->getConstPointer();
5724   for(int i=0;i<nbOfCells;i++,ci++)
5725     {
5726       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5727         {
5728           for(int j=0;j<5;j++,pt+=5,ptI++)
5729             {
5730               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5731               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];
5732               *retPt++=i;
5733               ptI[1]=ptI[0]+5;
5734             }
5735         }
5736       else
5737         {
5738           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5739           ptI[1]=ptI[0]+ci[1]-ci[0];
5740           ptI++;
5741           *retPt++=i;
5742         }
5743     }
5744   _nodal_connec->decrRef();
5745   _nodal_connec=newConn.retn();
5746   _nodal_connec_index->decrRef();
5747   _nodal_connec_index=newConnI.retn();
5748   computeTypes();
5749   updateTime();
5750   return ret.retn();
5751 }
5752
5753 /*!
5754  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5755  */
5756 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5757 {
5758   checkConnectivityFullyDefined();
5759   if(getMeshDimension()!=3)
5760     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5761   int nbOfCells=getNumberOfCells();
5762   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5763   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5764   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5765   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5766   int *retPt=ret->getPointer();
5767   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5768   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5769   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5770   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5771   int *pt=newConn->getPointer();
5772   int *ptI=newConnI->getPointer();
5773   ptI[0]=0;
5774   const int *oldc=_nodal_connec->getConstPointer();
5775   const int *ci=_nodal_connec_index->getConstPointer();
5776   for(int i=0;i<nbOfCells;i++,ci++)
5777     {
5778       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5779         {
5780           for(int j=0;j<6;j++,pt+=5,ptI++)
5781             {
5782               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5783               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];
5784               *retPt++=i;
5785               ptI[1]=ptI[0]+5;
5786             }
5787         }
5788       else
5789         {
5790           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5791           ptI[1]=ptI[0]+ci[1]-ci[0];
5792           ptI++;
5793           *retPt++=i;
5794         }
5795     }
5796   _nodal_connec->decrRef();
5797   _nodal_connec=newConn.retn();
5798   _nodal_connec_index->decrRef();
5799   _nodal_connec_index=newConnI.retn();
5800   computeTypes();
5801   updateTime();
5802   return ret.retn();
5803 }
5804
5805 /*!
5806  * 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.
5807  * This method completly ignore coordinates.
5808  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5809  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5810  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5811  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5812  */
5813 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5814 {
5815   checkFullyDefined();
5816   if(getMeshDimension()!=2)
5817     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5818   int nbOfCells=getNumberOfCells();
5819   int *connI=_nodal_connec_index->getPointer();
5820   int newConnLgth=0;
5821   for(int i=0;i<nbOfCells;i++,connI++)
5822     {
5823       int offset=descIndex[i];
5824       int nbOfEdges=descIndex[i+1]-offset;
5825       //
5826       bool ddirect=desc[offset+nbOfEdges-1]>0;
5827       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5828       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5829       for(int j=0;j<nbOfEdges;j++)
5830         {
5831           bool direct=desc[offset+j]>0;
5832           int edgeId=std::abs(desc[offset+j])-1;
5833           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5834             {
5835               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5836               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5837               int ref2=direct?id1:id2;
5838               if(ref==ref2)
5839                 {
5840                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5841                   newConnLgth+=nbOfSubNodes-1;
5842                   ref=direct?id2:id1;
5843                 }
5844               else
5845                 {
5846                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5847                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5848                 }
5849             }
5850           else
5851             {
5852               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5853             }
5854         }
5855       newConnLgth++;//+1 is for cell type
5856       connI[1]=newConnLgth;
5857     }
5858   //
5859   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5860   newConn->alloc(newConnLgth,1);
5861   int *work=newConn->getPointer();
5862   for(int i=0;i<nbOfCells;i++)
5863     {
5864       *work++=INTERP_KERNEL::NORM_POLYGON;
5865       int offset=descIndex[i];
5866       int nbOfEdges=descIndex[i+1]-offset;
5867       for(int j=0;j<nbOfEdges;j++)
5868         {
5869           bool direct=desc[offset+j]>0;
5870           int edgeId=std::abs(desc[offset+j])-1;
5871           if(direct)
5872             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5873           else
5874             {
5875               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5876               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5877               work=std::copy(it,it+nbOfSubNodes-1,work);
5878             }
5879         }
5880     }
5881   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5882   _types.clear();
5883   if(nbOfCells>0)
5884     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5885 }
5886
5887 /*!
5888  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5889  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5890  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5891  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5892  * so it can be useful to call mergeNodes() before calling this method.
5893  *  \throw If \a this->getMeshDimension() <= 1.
5894  *  \throw If the coordinates array is not set.
5895  *  \throw If the nodal connectivity of cells is not defined.
5896  */
5897 void MEDCouplingUMesh::convertDegeneratedCells()
5898 {
5899   checkFullyDefined();
5900   if(getMeshDimension()<=1)
5901     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5902   int nbOfCells=getNumberOfCells();
5903   if(nbOfCells<1)
5904     return ;
5905   int initMeshLgth=getMeshLength();
5906   int *conn=_nodal_connec->getPointer();
5907   int *index=_nodal_connec_index->getPointer();
5908   int posOfCurCell=0;
5909   int newPos=0;
5910   int lgthOfCurCell;
5911   for(int i=0;i<nbOfCells;i++)
5912     {
5913       lgthOfCurCell=index[i+1]-posOfCurCell;
5914       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5915       int newLgth;
5916       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5917                                                                                                      conn+newPos+1,newLgth);
5918       conn[newPos]=newType;
5919       newPos+=newLgth+1;
5920       posOfCurCell=index[i+1];
5921       index[i+1]=newPos;
5922     }
5923   if(newPos!=initMeshLgth)
5924     _nodal_connec->reAlloc(newPos);
5925   computeTypes();
5926 }
5927
5928 /*!
5929  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5930  * A cell is considered to be oriented correctly if an angle between its
5931  * normal vector and a given vector is less than \c PI / \c 2.
5932  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5933  *         cells. 
5934  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5935  *         checked.
5936  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5937  *         is not cleared before filling in.
5938  *  \throw If \a this->getMeshDimension() != 2.
5939  *  \throw If \a this->getSpaceDimension() != 3.
5940  *
5941  *  \if ENABLE_EXAMPLES
5942  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5943  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5944  *  \endif
5945  */
5946 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5947 {
5948   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5949     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5950   int nbOfCells=getNumberOfCells();
5951   const int *conn=_nodal_connec->getConstPointer();
5952   const int *connI=_nodal_connec_index->getConstPointer();
5953   const double *coordsPtr=_coords->getConstPointer();
5954   for(int i=0;i<nbOfCells;i++)
5955     {
5956       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5957       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5958         {
5959           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5960           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5961             cells.push_back(i);
5962         }
5963     }
5964 }
5965
5966 /*!
5967  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5968  * considered to be oriented correctly if an angle between its normal vector and a
5969  * given vector is less than \c PI / \c 2. 
5970  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5971  *         cells. 
5972  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5973  *         checked.
5974  *  \throw If \a this->getMeshDimension() != 2.
5975  *  \throw If \a this->getSpaceDimension() != 3.
5976  *
5977  *  \if ENABLE_EXAMPLES
5978  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5979  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5980  *  \endif
5981  */
5982 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5983 {
5984   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5985     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5986   int nbOfCells=getNumberOfCells();
5987   int *conn=_nodal_connec->getPointer();
5988   const int *connI=_nodal_connec_index->getConstPointer();
5989   const double *coordsPtr=_coords->getConstPointer();
5990   bool isModified=false;
5991   for(int i=0;i<nbOfCells;i++)
5992     {
5993       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5994       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5995         {
5996           bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5997           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5998             {
5999               isModified=true;
6000               if(!isQuadratic)
6001                 {
6002                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
6003                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
6004                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
6005                 }
6006               else
6007                 {
6008                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
6009                   std::vector<int> tmp0(sz-1),tmp1(sz);
6010                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
6011                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
6012                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
6013                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
6014                 }
6015             }
6016         }
6017     }
6018   if(isModified)
6019     _nodal_connec->declareAsNew();
6020   updateTime();
6021 }
6022
6023 /*!
6024  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6025  * oriented facets. The normal vector of the facet should point out of the cell.
6026  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6027  *         is not cleared before filling in.
6028  *  \throw If \a this->getMeshDimension() != 3.
6029  *  \throw If \a this->getSpaceDimension() != 3.
6030  *  \throw If the coordinates array is not set.
6031  *  \throw If the nodal connectivity of cells is not defined.
6032  *
6033  *  \if ENABLE_EXAMPLES
6034  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6035  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6036  *  \endif
6037  */
6038 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6039 {
6040   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6041     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6042   int nbOfCells=getNumberOfCells();
6043   const int *conn=_nodal_connec->getConstPointer();
6044   const int *connI=_nodal_connec_index->getConstPointer();
6045   const double *coordsPtr=_coords->getConstPointer();
6046   for(int i=0;i<nbOfCells;i++)
6047     {
6048       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6049       if(type==INTERP_KERNEL::NORM_POLYHED)
6050         {
6051           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6052             cells.push_back(i);
6053         }
6054     }
6055 }
6056
6057 /*!
6058  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6059  * out of the cell. 
6060  *  \throw If \a this->getMeshDimension() != 3.
6061  *  \throw If \a this->getSpaceDimension() != 3.
6062  *  \throw If the coordinates array is not set.
6063  *  \throw If the nodal connectivity of cells is not defined.
6064  *  \throw If the reparation fails.
6065  *
6066  *  \if ENABLE_EXAMPLES
6067  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6068  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6069  *  \endif
6070  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6071  */
6072 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6073 {
6074   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6075     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6076   int nbOfCells=getNumberOfCells();
6077   int *conn=_nodal_connec->getPointer();
6078   const int *connI=_nodal_connec_index->getConstPointer();
6079   const double *coordsPtr=_coords->getConstPointer();
6080   for(int i=0;i<nbOfCells;i++)
6081     {
6082       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6083       if(type==INTERP_KERNEL::NORM_POLYHED)
6084         {
6085           try
6086           {
6087               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6088                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6089           }
6090           catch(INTERP_KERNEL::Exception& e)
6091           {
6092               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6093               throw INTERP_KERNEL::Exception(oss.str().c_str());
6094           }
6095         }
6096     }
6097   updateTime();
6098 }
6099
6100 /*!
6101  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6102  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6103  * according to which the first facet of the cell should be oriented to have the normal vector
6104  * pointing out of cell.
6105  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6106  *         cells. The caller is to delete this array using decrRef() as it is no more
6107  *         needed. 
6108  *  \throw If \a this->getMeshDimension() != 3.
6109  *  \throw If \a this->getSpaceDimension() != 3.
6110  *  \throw If the coordinates array is not set.
6111  *  \throw If the nodal connectivity of cells is not defined.
6112  *
6113  *  \if ENABLE_EXAMPLES
6114  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6115  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6116  *  \endif
6117  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6118  */
6119 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6120 {
6121   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6122   if(getMeshDimension()!=3)
6123     throw INTERP_KERNEL::Exception(msg);
6124   int spaceDim=getSpaceDimension();
6125   if(spaceDim!=3)
6126     throw INTERP_KERNEL::Exception(msg);
6127   //
6128   int nbOfCells=getNumberOfCells();
6129   int *conn=_nodal_connec->getPointer();
6130   const int *connI=_nodal_connec_index->getConstPointer();
6131   const double *coo=getCoords()->getConstPointer();
6132   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6133   for(int i=0;i<nbOfCells;i++)
6134     {
6135       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6136       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6137         {
6138           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6139             {
6140               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6141               cells->pushBackSilent(i);
6142             }
6143         }
6144     }
6145   return cells.retn();
6146 }
6147
6148 /*!
6149  * This method is a faster method to correct orientation of all 3D cells in \a this.
6150  * 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.
6151  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6152  * 
6153  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6154  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6155  */
6156 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6157 {
6158   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6159     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6160   int nbOfCells=getNumberOfCells();
6161   int *conn=_nodal_connec->getPointer();
6162   const int *connI=_nodal_connec_index->getConstPointer();
6163   const double *coordsPtr=_coords->getConstPointer();
6164   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6165   for(int i=0;i<nbOfCells;i++)
6166     {
6167       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6168       switch(type)
6169       {
6170         case INTERP_KERNEL::NORM_TETRA4:
6171           {
6172             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6173               {
6174                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6175                 ret->pushBackSilent(i);
6176               }
6177             break;
6178           }
6179         case INTERP_KERNEL::NORM_PYRA5:
6180           {
6181             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6182               {
6183                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6184                 ret->pushBackSilent(i);
6185               }
6186             break;
6187           }
6188         case INTERP_KERNEL::NORM_PENTA6:
6189         case INTERP_KERNEL::NORM_HEXA8:
6190         case INTERP_KERNEL::NORM_HEXGP12:
6191           {
6192             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6193               {
6194                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6195                 ret->pushBackSilent(i);
6196               }
6197             break;
6198           }
6199         case INTERP_KERNEL::NORM_POLYHED:
6200           {
6201             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6202               {
6203                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6204                 ret->pushBackSilent(i);
6205               }
6206             break;
6207           }
6208         default:
6209           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 !");
6210       }
6211     }
6212   updateTime();
6213   return ret.retn();
6214 }
6215
6216 /*!
6217  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6218  * If it is not the case an exception will be thrown.
6219  * This method is fast because the first cell of \a this is used to compute the plane.
6220  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6221  * \param pos output of size at least 3 used to store a point owned of searched plane.
6222  */
6223 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6224 {
6225   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6226     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6227   const int *conn=_nodal_connec->getConstPointer();
6228   const int *connI=_nodal_connec_index->getConstPointer();
6229   const double *coordsPtr=_coords->getConstPointer();
6230   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6231   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6232 }
6233
6234 /*!
6235  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6236  * cells. Currently cells of the following types are treated:
6237  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6238  * For a cell of other type an exception is thrown.
6239  * Space dimension of a 2D mesh can be either 2 or 3.
6240  * The Edge Ratio of a cell \f$t\f$ is: 
6241  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6242  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6243  *  the smallest edge lengths of \f$t\f$.
6244  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6245  *          cells and one time, lying on \a this mesh. The caller is to delete this
6246  *          field using decrRef() as it is no more needed. 
6247  *  \throw If the coordinates array is not set.
6248  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6249  *  \throw If the connectivity data array has more than one component.
6250  *  \throw If the connectivity data array has a named component.
6251  *  \throw If the connectivity index data array has more than one component.
6252  *  \throw If the connectivity index data array has a named component.
6253  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6254  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6255  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6256  */
6257 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6258 {
6259   checkCoherency();
6260   int spaceDim=getSpaceDimension();
6261   int meshDim=getMeshDimension();
6262   if(spaceDim!=2 && spaceDim!=3)
6263     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6264   if(meshDim!=2 && meshDim!=3)
6265     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6266   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6267   ret->setMesh(this);
6268   int nbOfCells=getNumberOfCells();
6269   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6270   arr->alloc(nbOfCells,1);
6271   double *pt=arr->getPointer();
6272   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6273   const int *conn=_nodal_connec->getConstPointer();
6274   const int *connI=_nodal_connec_index->getConstPointer();
6275   const double *coo=_coords->getConstPointer();
6276   double tmp[12];
6277   for(int i=0;i<nbOfCells;i++,pt++)
6278     {
6279       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6280       switch(t)
6281       {
6282         case INTERP_KERNEL::NORM_TRI3:
6283           {
6284             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6285             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6286             break;
6287           }
6288         case INTERP_KERNEL::NORM_QUAD4:
6289           {
6290             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6291             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6292             break;
6293           }
6294         case INTERP_KERNEL::NORM_TETRA4:
6295           {
6296             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6297             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6298             break;
6299           }
6300         default:
6301           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6302       }
6303       conn+=connI[i+1]-connI[i];
6304     }
6305   ret->setName("EdgeRatio");
6306   ret->synchronizeTimeWithSupport();
6307   return ret.retn();
6308 }
6309
6310 /*!
6311  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6312  * cells. Currently cells of the following types are treated:
6313  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6314  * For a cell of other type an exception is thrown.
6315  * Space dimension of a 2D mesh can be either 2 or 3.
6316  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6317  *          cells and one time, lying on \a this mesh. The caller is to delete this
6318  *          field using decrRef() as it is no more needed. 
6319  *  \throw If the coordinates array is not set.
6320  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6321  *  \throw If the connectivity data array has more than one component.
6322  *  \throw If the connectivity data array has a named component.
6323  *  \throw If the connectivity index data array has more than one component.
6324  *  \throw If the connectivity index data array has a named component.
6325  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6326  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6327  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6328  */
6329 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6330 {
6331   checkCoherency();
6332   int spaceDim=getSpaceDimension();
6333   int meshDim=getMeshDimension();
6334   if(spaceDim!=2 && spaceDim!=3)
6335     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6336   if(meshDim!=2 && meshDim!=3)
6337     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6338   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6339   ret->setMesh(this);
6340   int nbOfCells=getNumberOfCells();
6341   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6342   arr->alloc(nbOfCells,1);
6343   double *pt=arr->getPointer();
6344   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6345   const int *conn=_nodal_connec->getConstPointer();
6346   const int *connI=_nodal_connec_index->getConstPointer();
6347   const double *coo=_coords->getConstPointer();
6348   double tmp[12];
6349   for(int i=0;i<nbOfCells;i++,pt++)
6350     {
6351       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6352       switch(t)
6353       {
6354         case INTERP_KERNEL::NORM_TRI3:
6355           {
6356             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6357             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6358             break;
6359           }
6360         case INTERP_KERNEL::NORM_QUAD4:
6361           {
6362             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6363             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6364             break;
6365           }
6366         case INTERP_KERNEL::NORM_TETRA4:
6367           {
6368             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6369             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6370             break;
6371           }
6372         default:
6373           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6374       }
6375       conn+=connI[i+1]-connI[i];
6376     }
6377   ret->setName("AspectRatio");
6378   ret->synchronizeTimeWithSupport();
6379   return ret.retn();
6380 }
6381
6382 /*!
6383  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6384  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6385  * treated: INTERP_KERNEL::NORM_QUAD4.
6386  * For a cell of other type an exception is thrown.
6387  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6388  *          cells and one time, lying on \a this mesh. The caller is to delete this
6389  *          field using decrRef() as it is no more needed. 
6390  *  \throw If the coordinates array is not set.
6391  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6392  *  \throw If the connectivity data array has more than one component.
6393  *  \throw If the connectivity data array has a named component.
6394  *  \throw If the connectivity index data array has more than one component.
6395  *  \throw If the connectivity index data array has a named component.
6396  *  \throw If \a this->getMeshDimension() != 2.
6397  *  \throw If \a this->getSpaceDimension() != 3.
6398  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6399  */
6400 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6401 {
6402   checkCoherency();
6403   int spaceDim=getSpaceDimension();
6404   int meshDim=getMeshDimension();
6405   if(spaceDim!=3)
6406     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6407   if(meshDim!=2)
6408     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6409   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6410   ret->setMesh(this);
6411   int nbOfCells=getNumberOfCells();
6412   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6413   arr->alloc(nbOfCells,1);
6414   double *pt=arr->getPointer();
6415   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6416   const int *conn=_nodal_connec->getConstPointer();
6417   const int *connI=_nodal_connec_index->getConstPointer();
6418   const double *coo=_coords->getConstPointer();
6419   double tmp[12];
6420   for(int i=0;i<nbOfCells;i++,pt++)
6421     {
6422       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6423       switch(t)
6424       {
6425         case INTERP_KERNEL::NORM_QUAD4:
6426           {
6427             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6428             *pt=INTERP_KERNEL::quadWarp(tmp);
6429             break;
6430           }
6431         default:
6432           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6433       }
6434       conn+=connI[i+1]-connI[i];
6435     }
6436   ret->setName("Warp");
6437   ret->synchronizeTimeWithSupport();
6438   return ret.retn();
6439 }
6440
6441
6442 /*!
6443  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6444  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6445  * treated: INTERP_KERNEL::NORM_QUAD4.
6446  * For a cell of other type an exception is thrown.
6447  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6448  *          cells and one time, lying on \a this mesh. The caller is to delete this
6449  *          field using decrRef() as it is no more needed. 
6450  *  \throw If the coordinates array is not set.
6451  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6452  *  \throw If the connectivity data array has more than one component.
6453  *  \throw If the connectivity data array has a named component.
6454  *  \throw If the connectivity index data array has more than one component.
6455  *  \throw If the connectivity index data array has a named component.
6456  *  \throw If \a this->getMeshDimension() != 2.
6457  *  \throw If \a this->getSpaceDimension() != 3.
6458  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6459  */
6460 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6461 {
6462   checkCoherency();
6463   int spaceDim=getSpaceDimension();
6464   int meshDim=getMeshDimension();
6465   if(spaceDim!=3)
6466     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6467   if(meshDim!=2)
6468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6469   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6470   ret->setMesh(this);
6471   int nbOfCells=getNumberOfCells();
6472   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6473   arr->alloc(nbOfCells,1);
6474   double *pt=arr->getPointer();
6475   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6476   const int *conn=_nodal_connec->getConstPointer();
6477   const int *connI=_nodal_connec_index->getConstPointer();
6478   const double *coo=_coords->getConstPointer();
6479   double tmp[12];
6480   for(int i=0;i<nbOfCells;i++,pt++)
6481     {
6482       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6483       switch(t)
6484       {
6485         case INTERP_KERNEL::NORM_QUAD4:
6486           {
6487             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6488             *pt=INTERP_KERNEL::quadSkew(tmp);
6489             break;
6490           }
6491         default:
6492           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6493       }
6494       conn+=connI[i+1]-connI[i];
6495     }
6496   ret->setName("Skew");
6497   ret->synchronizeTimeWithSupport();
6498   return ret.retn();
6499 }
6500
6501 /*!
6502  * This method aggregate the bbox of each cell and put it into bbox parameter.
6503  * 
6504  * \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)
6505  *                         For all other cases this input parameter is ignored.
6506  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6507  * 
6508  * \throw If \a this is not fully set (coordinates and connectivity).
6509  * \throw If a cell in \a this has no valid nodeId.
6510  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6511  */
6512 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6513 {
6514   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6515   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.
6516     return getBoundingBoxForBBTreeFast();
6517   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6518     {
6519       bool presenceOfQuadratic(false);
6520       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6521         {
6522           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6523           if(cm.isQuadratic())
6524             presenceOfQuadratic=true;
6525         }
6526       if(!presenceOfQuadratic)
6527         return getBoundingBoxForBBTreeFast();
6528       if(mDim==2 && sDim==2)
6529         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6530       else
6531         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6532     }
6533   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) !");
6534 }
6535
6536 /*!
6537  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6538  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6539  * 
6540  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6541  * 
6542  * \throw If \a this is not fully set (coordinates and connectivity).
6543  * \throw If a cell in \a this has no valid nodeId.
6544  */
6545 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6546 {
6547   checkFullyDefined();
6548   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6549   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6550   double *bbox(ret->getPointer());
6551   for(int i=0;i<nbOfCells*spaceDim;i++)
6552     {
6553       bbox[2*i]=std::numeric_limits<double>::max();
6554       bbox[2*i+1]=-std::numeric_limits<double>::max();
6555     }
6556   const double *coordsPtr(_coords->getConstPointer());
6557   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6558   for(int i=0;i<nbOfCells;i++)
6559     {
6560       int offset=connI[i]+1;
6561       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6562       for(int j=0;j<nbOfNodesForCell;j++)
6563         {
6564           int nodeId=conn[offset+j];
6565           if(nodeId>=0 && nodeId<nbOfNodes)
6566             {
6567               for(int k=0;k<spaceDim;k++)
6568                 {
6569                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6570                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6571                 }
6572               kk++;
6573             }
6574         }
6575       if(kk==0)
6576         {
6577           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6578           throw INTERP_KERNEL::Exception(oss.str().c_str());
6579         }
6580     }
6581   return ret.retn();
6582 }
6583
6584 /*!
6585  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6586  * useful for 2D meshes having quadratic cells
6587  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6588  * the two extremities of the arc of circle).
6589  * 
6590  * \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)
6591  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6592  * \throw If \a this is not fully defined.
6593  * \throw If \a this is not a mesh with meshDimension equal to 2.
6594  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6595  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6596  */
6597 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6598 {
6599   checkFullyDefined();
6600   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6601   if(spaceDim!=2 || mDim!=2)
6602     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!");
6603   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6604   double *bbox(ret->getPointer());
6605   const double *coords(_coords->getConstPointer());
6606   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6607   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6608     {
6609       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6610       int sz(connI[1]-connI[0]-1);
6611       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6612       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6613       INTERP_KERNEL::QuadraticPolygon *pol(0);
6614       for(int j=0;j<sz;j++)
6615         {
6616           int nodeId(conn[*connI+1+j]);
6617           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6618         }
6619       if(!cm.isQuadratic())
6620         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6621       else
6622         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6623       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6624       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6625     }
6626   return ret.retn();
6627 }
6628
6629 /*!
6630  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6631  * useful for 2D meshes having quadratic cells
6632  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6633  * the two extremities of the arc of circle).
6634  * 
6635  * \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)
6636  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6637  * \throw If \a this is not fully defined.
6638  * \throw If \a this is not a mesh with meshDimension equal to 1.
6639  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6640  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6641  */
6642 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6643 {
6644   checkFullyDefined();
6645   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6646   if(spaceDim!=2 || mDim!=1)
6647     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!");
6648   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6649   double *bbox(ret->getPointer());
6650   const double *coords(_coords->getConstPointer());
6651   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6652   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6653     {
6654       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6655       int sz(connI[1]-connI[0]-1);
6656       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6657       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6658       INTERP_KERNEL::Edge *edge(0);
6659       for(int j=0;j<sz;j++)
6660         {
6661           int nodeId(conn[*connI+1+j]);
6662           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6663         }
6664       if(!cm.isQuadratic())
6665         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6666       else
6667         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6668       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6669       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6670     }
6671   return ret.retn();
6672 }
6673
6674 /// @cond INTERNAL
6675
6676 namespace ParaMEDMEMImpl
6677 {
6678   class ConnReader
6679   {
6680   public:
6681     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6682     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6683   private:
6684     const int *_conn;
6685     int _val;
6686   };
6687
6688   class ConnReader2
6689   {
6690   public:
6691     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6692     bool operator() (const int& pos) { return _conn[pos]==_val; }
6693   private:
6694     const int *_conn;
6695     int _val;
6696   };
6697 }
6698
6699 /// @endcond
6700
6701 /*!
6702  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6703  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6704  * \a this is composed in cell types.
6705  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6706  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6707  * This parameter is kept only for compatibility with other methode listed above.
6708  */
6709 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6710 {
6711   checkConnectivityFullyDefined();
6712   const int *conn=_nodal_connec->getConstPointer();
6713   const int *connI=_nodal_connec_index->getConstPointer();
6714   const int *work=connI;
6715   int nbOfCells=getNumberOfCells();
6716   std::size_t n=getAllGeoTypes().size();
6717   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6718   std::set<INTERP_KERNEL::NormalizedCellType> types;
6719   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6720     {
6721       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6722       if(types.find(typ)!=types.end())
6723         {
6724           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6725           oss << " is not contiguous !";
6726           throw INTERP_KERNEL::Exception(oss.str().c_str());
6727         }
6728       types.insert(typ);
6729       ret[3*i]=typ;
6730       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6731       ret[3*i+1]=(int)std::distance(work,work2);
6732       work=work2;
6733     }
6734   return ret;
6735 }
6736
6737 /*!
6738  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6739  * only for types cell, type node is not managed.
6740  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6741  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6742  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6743  * If 2 or more same geometric type is in \a code and exception is thrown too.
6744  *
6745  * This method firstly checks
6746  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6747  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6748  * an exception is thrown too.
6749  * 
6750  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6751  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6752  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6753  */
6754 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6755 {
6756   if(code.empty())
6757     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6758   std::size_t sz=code.size();
6759   std::size_t n=sz/3;
6760   if(sz%3!=0)
6761     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6762   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6763   int nb=0;
6764   bool isNoPflUsed=true;
6765   for(std::size_t i=0;i<n;i++)
6766     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6767       {
6768         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6769         nb+=code[3*i+1];
6770         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6771           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6772         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6773       }
6774   if(types.size()!=n)
6775     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6776   if(isNoPflUsed)
6777     {
6778       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6779         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6780       if(types.size()==_types.size())
6781         return 0;
6782     }
6783   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6784   ret->alloc(nb,1);
6785   int *retPtr=ret->getPointer();
6786   const int *connI=_nodal_connec_index->getConstPointer();
6787   const int *conn=_nodal_connec->getConstPointer();
6788   int nbOfCells=getNumberOfCells();
6789   const int *i=connI;
6790   int kk=0;
6791   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6792     {
6793       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6794       int offset=(int)std::distance(connI,i);
6795       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6796       int nbOfCellsOfCurType=(int)std::distance(i,j);
6797       if(code[3*kk+2]==-1)
6798         for(int k=0;k<nbOfCellsOfCurType;k++)
6799           *retPtr++=k+offset;
6800       else
6801         {
6802           int idInIdsPerType=code[3*kk+2];
6803           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6804             {
6805               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6806               if(zePfl)
6807                 {
6808                   zePfl->checkAllocated();
6809                   if(zePfl->getNumberOfComponents()==1)
6810                     {
6811                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6812                         {
6813                           if(*k>=0 && *k<nbOfCellsOfCurType)
6814                             *retPtr=(*k)+offset;
6815                           else
6816                             {
6817                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6818                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6819                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6820                             }
6821                         }
6822                     }
6823                   else
6824                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6825                 }
6826               else
6827                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6828             }
6829           else
6830             {
6831               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6832               oss << " should be in [0," << idsPerType.size() << ") !";
6833               throw INTERP_KERNEL::Exception(oss.str().c_str());
6834             }
6835         }
6836       i=j;
6837     }
6838   return ret.retn();
6839 }
6840
6841 /*!
6842  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6843  * 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.
6844  * 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.
6845  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6846  * 
6847  * \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.
6848  * \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,
6849  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6850  * \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.
6851  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6852  * \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
6853  */
6854 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6855 {
6856   if(!profile)
6857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6858   if(profile->getNumberOfComponents()!=1)
6859     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6860   checkConnectivityFullyDefined();
6861   const int *conn=_nodal_connec->getConstPointer();
6862   const int *connI=_nodal_connec_index->getConstPointer();
6863   int nbOfCells=getNumberOfCells();
6864   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6865   std::vector<int> typeRangeVals(1);
6866   for(const int *i=connI;i!=connI+nbOfCells;)
6867     {
6868       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6869       if(std::find(types.begin(),types.end(),curType)!=types.end())
6870         {
6871           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6872         }
6873       types.push_back(curType);
6874       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6875       typeRangeVals.push_back((int)std::distance(connI,i));
6876     }
6877   //
6878   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6879   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6881   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6883   //
6884   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6885   code.resize(3*nbOfCastsFinal);
6886   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6887   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6888   for(int i=0;i<nbOfCastsFinal;i++)
6889     {
6890       int castId=castsPresent->getIJ(i,0);
6891       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6892       idsInPflPerType2.push_back(tmp3);
6893       code[3*i]=(int)types[castId];
6894       code[3*i+1]=tmp3->getNumberOfTuples();
6895       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6896       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6897         {
6898           tmp4->copyStringInfoFrom(*profile);
6899           idsPerType2.push_back(tmp4);
6900           code[3*i+2]=(int)idsPerType2.size()-1;
6901         }
6902       else
6903         {
6904           code[3*i+2]=-1;
6905         }
6906     }
6907   std::size_t sz2=idsInPflPerType2.size();
6908   idsInPflPerType.resize(sz2);
6909   for(std::size_t i=0;i<sz2;i++)
6910     {
6911       DataArrayInt *locDa=idsInPflPerType2[i];
6912       locDa->incrRef();
6913       idsInPflPerType[i]=locDa;
6914     }
6915   std::size_t sz=idsPerType2.size();
6916   idsPerType.resize(sz);
6917   for(std::size_t i=0;i<sz;i++)
6918     {
6919       DataArrayInt *locDa=idsPerType2[i];
6920       locDa->incrRef();
6921       idsPerType[i]=locDa;
6922     }
6923 }
6924
6925 /*!
6926  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6927  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6928  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6929  * 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.
6930  */
6931 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6932 {
6933   checkFullyDefined();
6934   nM1LevMesh->checkFullyDefined();
6935   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6936     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6937   if(_coords!=nM1LevMesh->getCoords())
6938     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6939   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6940   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6941   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6942   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6943   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6944   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6945   tmp->setConnectivity(tmp0,tmp1);
6946   tmp->renumberCells(ret0->getConstPointer(),false);
6947   revDesc=tmp->getNodalConnectivity();
6948   revDescIndx=tmp->getNodalConnectivityIndex();
6949   DataArrayInt *ret=0;
6950   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6951     {
6952       int tmp2;
6953       ret->getMaxValue(tmp2);
6954       ret->decrRef();
6955       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6956       throw INTERP_KERNEL::Exception(oss.str().c_str());
6957     }
6958   nM1LevMeshIds=ret;
6959   //
6960   revDesc->incrRef();
6961   revDescIndx->incrRef();
6962   ret1->incrRef();
6963   ret0->incrRef();
6964   meshnM1Old2New=ret0;
6965   return ret1;
6966 }
6967
6968 /*!
6969  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6970  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6971  * in "Old to New" mode.
6972  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6973  *          this array using decrRef() as it is no more needed.
6974  *  \throw If the nodal connectivity of cells is not defined.
6975  */
6976 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6977 {
6978   checkConnectivityFullyDefined();
6979   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6980   renumberCells(ret->getConstPointer(),false);
6981   return ret.retn();
6982 }
6983
6984 /*!
6985  * This methods checks that cells are sorted by their types.
6986  * This method makes asumption (no check) that connectivity is correctly set before calling.
6987  */
6988 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6989 {
6990   checkFullyDefined();
6991   const int *conn=_nodal_connec->getConstPointer();
6992   const int *connI=_nodal_connec_index->getConstPointer();
6993   int nbOfCells=getNumberOfCells();
6994   std::set<INTERP_KERNEL::NormalizedCellType> types;
6995   for(const int *i=connI;i!=connI+nbOfCells;)
6996     {
6997       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6998       if(types.find(curType)!=types.end())
6999         return false;
7000       types.insert(curType);
7001       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7002     }
7003   return true;
7004 }
7005
7006 /*!
7007  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7008  * The geometric type order is specified by MED file.
7009  * 
7010  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7011  */
7012 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7013 {
7014   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7015 }
7016
7017 /*!
7018  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7019  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7020  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7021  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7022  */
7023 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7024 {
7025   checkFullyDefined();
7026   const int *conn=_nodal_connec->getConstPointer();
7027   const int *connI=_nodal_connec_index->getConstPointer();
7028   int nbOfCells=getNumberOfCells();
7029   if(nbOfCells==0)
7030     return true;
7031   int lastPos=-1;
7032   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7033   for(const int *i=connI;i!=connI+nbOfCells;)
7034     {
7035       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7036       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7037       if(isTypeExists!=orderEnd)
7038         {
7039           int pos=(int)std::distance(orderBg,isTypeExists);
7040           if(pos<=lastPos)
7041             return false;
7042           lastPos=pos;
7043           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7044         }
7045       else
7046         {
7047           if(sg.find(curType)==sg.end())
7048             {
7049               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7050               sg.insert(curType);
7051             }
7052           else
7053             return false;
7054         }
7055     }
7056   return true;
7057 }
7058
7059 /*!
7060  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7061  * 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
7062  * 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'.
7063  */
7064 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7065 {
7066   checkConnectivityFullyDefined();
7067   int nbOfCells=getNumberOfCells();
7068   const int *conn=_nodal_connec->getConstPointer();
7069   const int *connI=_nodal_connec_index->getConstPointer();
7070   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7071   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7072   tmpa->alloc(nbOfCells,1);
7073   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7074   tmpb->fillWithZero();
7075   int *tmp=tmpa->getPointer();
7076   int *tmp2=tmpb->getPointer();
7077   for(const int *i=connI;i!=connI+nbOfCells;i++)
7078     {
7079       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7080       if(where!=orderEnd)
7081         {
7082           int pos=(int)std::distance(orderBg,where);
7083           tmp2[pos]++;
7084           tmp[std::distance(connI,i)]=pos;
7085         }
7086       else
7087         {
7088           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7089           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7090           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7091           throw INTERP_KERNEL::Exception(oss.str().c_str());
7092         }
7093     }
7094   nbPerType=tmpb.retn();
7095   return tmpa.retn();
7096 }
7097
7098 /*!
7099  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7100  *
7101  * \return a new object containing the old to new correspondance.
7102  *
7103  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7104  */
7105 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7106 {
7107   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7108 }
7109
7110 /*!
7111  * 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.
7112  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7113  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7114  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7115  */
7116 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7117 {
7118   DataArrayInt *nbPerType=0;
7119   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7120   nbPerType->decrRef();
7121   return tmpa->buildPermArrPerLevel();
7122 }
7123
7124 /*!
7125  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7126  * The number of cells remains unchanged after the call of this method.
7127  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7128  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7129  *
7130  * \return the array giving the correspondance old to new.
7131  */
7132 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7133 {
7134   checkFullyDefined();
7135   computeTypes();
7136   const int *conn=_nodal_connec->getConstPointer();
7137   const int *connI=_nodal_connec_index->getConstPointer();
7138   int nbOfCells=getNumberOfCells();
7139   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7140   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7141     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7142       {
7143         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7144         types.push_back(curType);
7145         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7146       }
7147   DataArrayInt *ret=DataArrayInt::New();
7148   ret->alloc(nbOfCells,1);
7149   int *retPtr=ret->getPointer();
7150   std::fill(retPtr,retPtr+nbOfCells,-1);
7151   int newCellId=0;
7152   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7153     {
7154       for(const int *i=connI;i!=connI+nbOfCells;i++)
7155         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7156           retPtr[std::distance(connI,i)]=newCellId++;
7157     }
7158   renumberCells(retPtr,false);
7159   return ret;
7160 }
7161
7162 /*!
7163  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7164  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7165  * This method makes asumption that connectivity is correctly set before calling.
7166  */
7167 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7168 {
7169   checkConnectivityFullyDefined();
7170   const int *conn=_nodal_connec->getConstPointer();
7171   const int *connI=_nodal_connec_index->getConstPointer();
7172   int nbOfCells=getNumberOfCells();
7173   std::vector<MEDCouplingUMesh *> ret;
7174   for(const int *i=connI;i!=connI+nbOfCells;)
7175     {
7176       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7177       int beginCellId=(int)std::distance(connI,i);
7178       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7179       int endCellId=(int)std::distance(connI,i);
7180       int sz=endCellId-beginCellId;
7181       int *cells=new int[sz];
7182       for(int j=0;j<sz;j++)
7183         cells[j]=beginCellId+j;
7184       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7185       delete [] cells;
7186       ret.push_back(m);
7187     }
7188   return ret;
7189 }
7190
7191 /*!
7192  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7193  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7194  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7195  *
7196  * \return a newly allocated instance, that the caller must manage.
7197  * \throw If \a this contains more than one geometric type.
7198  * \throw If the nodal connectivity of \a this is not fully defined.
7199  * \throw If the internal data is not coherent.
7200  */
7201 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7202 {
7203   checkConnectivityFullyDefined();
7204   if(_types.size()!=1)
7205     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7206   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7207   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7208   ret->setCoords(getCoords());
7209   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7210   if(retC)
7211     {
7212       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7213       retC->setNodalConnectivity(c);
7214     }
7215   else
7216     {
7217       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7218       if(!retD)
7219         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7220       DataArrayInt *c=0,*ci=0;
7221       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7222       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7223       retD->setNodalConnectivity(cs,cis);
7224     }
7225   return ret.retn();
7226 }
7227
7228 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7229 {
7230   checkConnectivityFullyDefined();
7231   if(_types.size()!=1)
7232     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7233   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7234   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7235   if(cm.isDynamic())
7236     {
7237       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7238       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7239       throw INTERP_KERNEL::Exception(oss.str().c_str());
7240     }
7241   int nbCells=getNumberOfCells();
7242   int typi=(int)typ;
7243   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7245   int *outPtr=connOut->getPointer();
7246   const int *conn=_nodal_connec->begin();
7247   const int *connI=_nodal_connec_index->begin();
7248   nbNodesPerCell++;
7249   for(int i=0;i<nbCells;i++,connI++)
7250     {
7251       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7252         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7253       else
7254         {
7255           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 << ") !";
7256           throw INTERP_KERNEL::Exception(oss.str().c_str());
7257         }
7258     }
7259   return connOut.retn();
7260 }
7261
7262 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7263 {
7264   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7265   checkConnectivityFullyDefined();
7266   if(_types.size()!=1)
7267     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7268   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7269   if(lgth<nbCells)
7270     throw INTERP_KERNEL::Exception(msg0);
7271   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7272   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7273   int *cp(c->getPointer()),*cip(ci->getPointer());
7274   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7275   cip[0]=0;
7276   for(int i=0;i<nbCells;i++,cip++,incip++)
7277     {
7278       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7279       int delta(stop-strt);
7280       if(delta>=1)
7281         {
7282           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7283             cp=std::copy(incp+strt,incp+stop,cp);
7284           else
7285             throw INTERP_KERNEL::Exception(msg0);
7286         }
7287       else
7288         throw INTERP_KERNEL::Exception(msg0);
7289       cip[1]=cip[0]+delta;
7290     }
7291   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7292 }
7293
7294 /*!
7295  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7296  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7297  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7298  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7299  * are not used here to avoid the build of big permutation array.
7300  *
7301  * \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
7302  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7303  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7304  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7305  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7306  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7307  * \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
7308  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7309  */
7310 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7311                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7312                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7313 {
7314   std::vector<const MEDCouplingUMesh *> ms2;
7315   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7316     if(*it)
7317       {
7318         (*it)->checkConnectivityFullyDefined();
7319         ms2.push_back(*it);
7320       }
7321   if(ms2.empty())
7322     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7323   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7324   int meshDim=ms2[0]->getMeshDimension();
7325   std::vector<const MEDCouplingUMesh *> m1ssm;
7326   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7327   //
7328   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7329   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7330   int fake=0,rk=0;
7331   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7332   ret1->alloc(0,1); ret2->alloc(0,1);
7333   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7334     {
7335       if(meshDim!=(*it)->getMeshDimension())
7336         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7337       if(refCoo!=(*it)->getCoords())
7338         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7339       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7340       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7341       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7342       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7343         {
7344           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7345           m1ssmSingleAuto.push_back(singleCell);
7346           m1ssmSingle.push_back(singleCell);
7347           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7348         }
7349     }
7350   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7351   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7352   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7353   for(std::size_t i=0;i<m1ssm.size();i++)
7354     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7355   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7356   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7357   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7358   return ret0.retn();
7359 }
7360
7361 /*!
7362  * This method returns a newly created DataArrayInt instance.
7363  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7364  */
7365 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7366 {
7367   checkFullyDefined();
7368   const int *conn=_nodal_connec->getConstPointer();
7369   const int *connIndex=_nodal_connec_index->getConstPointer();
7370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7371   for(const int *w=begin;w!=end;w++)
7372     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7373       ret->pushBackSilent(*w);
7374   return ret.retn();
7375 }
7376
7377 /*!
7378  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7379  * are in [0:getNumberOfCells())
7380  */
7381 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7382 {
7383   checkFullyDefined();
7384   const int *conn=_nodal_connec->getConstPointer();
7385   const int *connI=_nodal_connec_index->getConstPointer();
7386   int nbOfCells=getNumberOfCells();
7387   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7388   int *tmp=new int[nbOfCells];
7389   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7390     {
7391       int j=0;
7392       for(const int *i=connI;i!=connI+nbOfCells;i++)
7393         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7394           tmp[std::distance(connI,i)]=j++;
7395     }
7396   DataArrayInt *ret=DataArrayInt::New();
7397   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7398   ret->copyStringInfoFrom(*da);
7399   int *retPtr=ret->getPointer();
7400   const int *daPtr=da->getConstPointer();
7401   int nbOfElems=da->getNbOfElems();
7402   for(int k=0;k<nbOfElems;k++)
7403     retPtr[k]=tmp[daPtr[k]];
7404   delete [] tmp;
7405   return ret;
7406 }
7407
7408 /*!
7409  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7410  * This method \b works \b for mesh sorted by type.
7411  * cells whose ids is in 'idsPerGeoType' array.
7412  * This method conserves coords and name of mesh.
7413  */
7414 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7415 {
7416   std::vector<int> code=getDistributionOfTypes();
7417   std::size_t nOfTypesInThis=code.size()/3;
7418   int sz=0,szOfType=0;
7419   for(std::size_t i=0;i<nOfTypesInThis;i++)
7420     {
7421       if(code[3*i]!=type)
7422         sz+=code[3*i+1];
7423       else
7424         szOfType=code[3*i+1];
7425     }
7426   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7427     if(*work<0 || *work>=szOfType)
7428       {
7429         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7430         oss << ". It should be in [0," << szOfType << ") !";
7431         throw INTERP_KERNEL::Exception(oss.str().c_str());
7432       }
7433   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7434   int *idsPtr=idsTokeep->getPointer();
7435   int offset=0;
7436   for(std::size_t i=0;i<nOfTypesInThis;i++)
7437     {
7438       if(code[3*i]!=type)
7439         for(int j=0;j<code[3*i+1];j++)
7440           *idsPtr++=offset+j;
7441       else
7442         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7443       offset+=code[3*i+1];
7444     }
7445   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7446   ret->copyTinyInfoFrom(this);
7447   return ret.retn();
7448 }
7449
7450 /*!
7451  * This method returns a vector of size 'this->getNumberOfCells()'.
7452  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7453  */
7454 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7455 {
7456   int ncell=getNumberOfCells();
7457   std::vector<bool> ret(ncell);
7458   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7459   const int *c=getNodalConnectivity()->getConstPointer();
7460   for(int i=0;i<ncell;i++)
7461     {
7462       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7463       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7464       ret[i]=cm.isQuadratic();
7465     }
7466   return ret;
7467 }
7468
7469 /*!
7470  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7471  */
7472 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7473 {
7474   if(other->getType()!=UNSTRUCTURED)
7475     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7476   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7477   return MergeUMeshes(this,otherC);
7478 }
7479
7480 /*!
7481  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7482  * computed by averaging coordinates of cell nodes, so this method is not a right
7483  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7484  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7485  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7486  *          components. The caller is to delete this array using decrRef() as it is
7487  *          no more needed.
7488  *  \throw If the coordinates array is not set.
7489  *  \throw If the nodal connectivity of cells is not defined.
7490  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7491  */
7492 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7493 {
7494   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7495   int spaceDim=getSpaceDimension();
7496   int nbOfCells=getNumberOfCells();
7497   ret->alloc(nbOfCells,spaceDim);
7498   ret->copyStringInfoFrom(*getCoords());
7499   double *ptToFill=ret->getPointer();
7500   const int *nodal=_nodal_connec->getConstPointer();
7501   const int *nodalI=_nodal_connec_index->getConstPointer();
7502   const double *coor=_coords->getConstPointer();
7503   for(int i=0;i<nbOfCells;i++)
7504     {
7505       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7506       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7507       ptToFill+=spaceDim;
7508     }
7509   return ret.retn();
7510 }
7511
7512 /*!
7513  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7514  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7515  * 
7516  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7517  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7518  * 
7519  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7520  * \throw If \a this is not fully defined (coordinates and connectivity)
7521  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7522  */
7523 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7524 {
7525   checkFullyDefined();
7526   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7527   int spaceDim=getSpaceDimension();
7528   int nbOfCells=getNumberOfCells();
7529   int nbOfNodes=getNumberOfNodes();
7530   ret->alloc(nbOfCells,spaceDim);
7531   double *ptToFill=ret->getPointer();
7532   const int *nodal=_nodal_connec->getConstPointer();
7533   const int *nodalI=_nodal_connec_index->getConstPointer();
7534   const double *coor=_coords->getConstPointer();
7535   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7536     {
7537       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7538       std::fill(ptToFill,ptToFill+spaceDim,0.);
7539       if(type!=INTERP_KERNEL::NORM_POLYHED)
7540         {
7541           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7542             {
7543               if(*conn>=0 && *conn<nbOfNodes)
7544                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7545               else
7546                 {
7547                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7548                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7549                 }
7550             }
7551           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7552           if(nbOfNodesInCell>0)
7553             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7554           else
7555             {
7556               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7557               throw INTERP_KERNEL::Exception(oss.str().c_str());
7558             }
7559         }
7560       else
7561         {
7562           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7563           s.erase(-1);
7564           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7565             {
7566               if(*it>=0 && *it<nbOfNodes)
7567                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7568               else
7569                 {
7570                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7571                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7572                 }
7573             }
7574           if(!s.empty())
7575             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7576           else
7577             {
7578               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7579               throw INTERP_KERNEL::Exception(oss.str().c_str());
7580             }
7581         }
7582     }
7583   return ret.retn();
7584 }
7585
7586 /*!
7587  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7588  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7589  * are specified via an array of cell ids. 
7590  *  \warning Validity of the specified cell ids is not checked! 
7591  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7592  *  \param [in] begin - an array of cell ids of interest.
7593  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7594  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7595  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7596  *          caller is to delete this array using decrRef() as it is no more needed. 
7597  *  \throw If the coordinates array is not set.
7598  *  \throw If the nodal connectivity of cells is not defined.
7599  *
7600  *  \if ENABLE_EXAMPLES
7601  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7602  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7603  *  \endif
7604  */
7605 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7606 {
7607   DataArrayDouble *ret=DataArrayDouble::New();
7608   int spaceDim=getSpaceDimension();
7609   int nbOfTuple=(int)std::distance(begin,end);
7610   ret->alloc(nbOfTuple,spaceDim);
7611   double *ptToFill=ret->getPointer();
7612   double *tmp=new double[spaceDim];
7613   const int *nodal=_nodal_connec->getConstPointer();
7614   const int *nodalI=_nodal_connec_index->getConstPointer();
7615   const double *coor=_coords->getConstPointer();
7616   for(const int *w=begin;w!=end;w++)
7617     {
7618       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7619       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7620       ptToFill+=spaceDim;
7621     }
7622   delete [] tmp;
7623   return ret;
7624 }
7625
7626 /*!
7627  * 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".
7628  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7629  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7630  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7631  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7632  * 
7633  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7634  * \throw If spaceDim!=3 or meshDim!=2.
7635  * \throw If connectivity of \a this is invalid.
7636  * \throw If connectivity of a cell in \a this points to an invalid node.
7637  */
7638 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7639 {
7640   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7641   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7642   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7643     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7644   ret->alloc(nbOfCells,4);
7645   double *retPtr(ret->getPointer());
7646   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7647   const double *coor(_coords->begin());
7648   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7649     {
7650       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7651       if(nodalI[1]-nodalI[0]>=3)
7652         {
7653           for(int j=0;j<3;j++)
7654             {
7655               int nodeId(nodal[nodalI[0]+1+j]);
7656               if(nodeId>=0 && nodeId<nbOfNodes)
7657                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7658               else
7659                 {
7660                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7661                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7662                 }
7663             }
7664         }
7665       else
7666         {
7667           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7668           throw INTERP_KERNEL::Exception(oss.str().c_str());
7669         }
7670       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7671       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7672     }
7673   return ret.retn();
7674 }
7675
7676 /*!
7677  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7678  * 
7679  */
7680 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7681 {
7682   if(!da)
7683     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7684   da->checkAllocated();
7685   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7686   ret->setCoords(da);
7687   int nbOfTuples=da->getNumberOfTuples();
7688   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7689   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7690   c->alloc(2*nbOfTuples,1);
7691   cI->alloc(nbOfTuples+1,1);
7692   int *cp=c->getPointer();
7693   int *cip=cI->getPointer();
7694   *cip++=0;
7695   for(int i=0;i<nbOfTuples;i++)
7696     {
7697       *cp++=INTERP_KERNEL::NORM_POINT1;
7698       *cp++=i;
7699       *cip++=2*(i+1);
7700     }
7701   ret->setConnectivity(c,cI,true);
7702   return ret.retn();
7703 }
7704 /*!
7705  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7706  * Cells and nodes of
7707  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7708  *  \param [in] mesh1 - the first mesh.
7709  *  \param [in] mesh2 - the second mesh.
7710  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7711  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7712  *          is no more needed.
7713  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7714  *  \throw If the coordinates array is not set in none of the meshes.
7715  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7716  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7717  */
7718 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7719 {
7720   std::vector<const MEDCouplingUMesh *> tmp(2);
7721   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7722   return MergeUMeshes(tmp);
7723 }
7724
7725 /*!
7726  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7727  * Cells and nodes of
7728  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7729  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7730  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7731  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7732  *          is no more needed.
7733  *  \throw If \a a.size() == 0.
7734  *  \throw If \a a[ *i* ] == NULL.
7735  *  \throw If the coordinates array is not set in none of the meshes.
7736  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7737  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7738  */
7739 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7740 {
7741   std::size_t sz=a.size();
7742   if(sz==0)
7743     return MergeUMeshesLL(a);
7744   for(std::size_t ii=0;ii<sz;ii++)
7745     if(!a[ii])
7746       {
7747         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7748         throw INTERP_KERNEL::Exception(oss.str().c_str());
7749       }
7750   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7751   std::vector< const MEDCouplingUMesh * > aa(sz);
7752   int spaceDim=-3;
7753   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7754     {
7755       const MEDCouplingUMesh *cur=a[i];
7756       const DataArrayDouble *coo=cur->getCoords();
7757       if(coo)
7758         spaceDim=coo->getNumberOfComponents();
7759     }
7760   if(spaceDim==-3)
7761     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7762   for(std::size_t i=0;i<sz;i++)
7763     {
7764       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7765       aa[i]=bb[i];
7766     }
7767   return MergeUMeshesLL(aa);
7768 }
7769
7770 /// @cond INTERNAL
7771
7772 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7773 {
7774   if(a.empty())
7775     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7776   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7777   int meshDim=(*it)->getMeshDimension();
7778   int nbOfCells=(*it)->getNumberOfCells();
7779   int meshLgth=(*it++)->getMeshLength();
7780   for(;it!=a.end();it++)
7781     {
7782       if(meshDim!=(*it)->getMeshDimension())
7783         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7784       nbOfCells+=(*it)->getNumberOfCells();
7785       meshLgth+=(*it)->getMeshLength();
7786     }
7787   std::vector<const MEDCouplingPointSet *> aps(a.size());
7788   std::copy(a.begin(),a.end(),aps.begin());
7789   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7790   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7791   ret->setCoords(pts);
7792   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7793   c->alloc(meshLgth,1);
7794   int *cPtr=c->getPointer();
7795   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7796   cI->alloc(nbOfCells+1,1);
7797   int *cIPtr=cI->getPointer();
7798   *cIPtr++=0;
7799   int offset=0;
7800   int offset2=0;
7801   for(it=a.begin();it!=a.end();it++)
7802     {
7803       int curNbOfCell=(*it)->getNumberOfCells();
7804       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7805       const int *curC=(*it)->_nodal_connec->getConstPointer();
7806       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7807       for(int j=0;j<curNbOfCell;j++)
7808         {
7809           const int *src=curC+curCI[j];
7810           *cPtr++=*src++;
7811           for(;src!=curC+curCI[j+1];src++,cPtr++)
7812             {
7813               if(*src!=-1)
7814                 *cPtr=*src+offset2;
7815               else
7816                 *cPtr=-1;
7817             }
7818         }
7819       offset+=curCI[curNbOfCell];
7820       offset2+=(*it)->getNumberOfNodes();
7821     }
7822   //
7823   ret->setConnectivity(c,cI,true);
7824   return ret.retn();
7825 }
7826
7827 /// @endcond
7828
7829 /*!
7830  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7831  * dimension and sharing the node coordinates array.
7832  * All cells of the first mesh precede all cells of the second mesh
7833  * within the result mesh. 
7834  *  \param [in] mesh1 - the first mesh.
7835  *  \param [in] mesh2 - the second mesh.
7836  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7837  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7838  *          is no more needed.
7839  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7840  *  \throw If the meshes do not share the node coordinates array.
7841  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7842  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7843  */
7844 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7845 {
7846   std::vector<const MEDCouplingUMesh *> tmp(2);
7847   tmp[0]=mesh1; tmp[1]=mesh2;
7848   return MergeUMeshesOnSameCoords(tmp);
7849 }
7850
7851 /*!
7852  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7853  * dimension and sharing the node coordinates array.
7854  * All cells of the *i*-th mesh precede all cells of the
7855  * (*i*+1)-th mesh within the result mesh.
7856  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7857  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7858  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7859  *          is no more needed.
7860  *  \throw If \a a.size() == 0.
7861  *  \throw If \a a[ *i* ] == NULL.
7862  *  \throw If the meshes do not share the node coordinates array.
7863  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7864  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7865  */
7866 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7867 {
7868   if(meshes.empty())
7869     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7870   for(std::size_t ii=0;ii<meshes.size();ii++)
7871     if(!meshes[ii])
7872       {
7873         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7874         throw INTERP_KERNEL::Exception(oss.str().c_str());
7875       }
7876   const DataArrayDouble *coords=meshes.front()->getCoords();
7877   int meshDim=meshes.front()->getMeshDimension();
7878   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7879   int meshLgth=0;
7880   int meshIndexLgth=0;
7881   for(;iter!=meshes.end();iter++)
7882     {
7883       if(coords!=(*iter)->getCoords())
7884         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7885       if(meshDim!=(*iter)->getMeshDimension())
7886         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7887       meshLgth+=(*iter)->getMeshLength();
7888       meshIndexLgth+=(*iter)->getNumberOfCells();
7889     }
7890   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7891   nodal->alloc(meshLgth,1);
7892   int *nodalPtr=nodal->getPointer();
7893   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7894   nodalIndex->alloc(meshIndexLgth+1,1);
7895   int *nodalIndexPtr=nodalIndex->getPointer();
7896   int offset=0;
7897   for(iter=meshes.begin();iter!=meshes.end();iter++)
7898     {
7899       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7900       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7901       int nbOfCells=(*iter)->getNumberOfCells();
7902       int meshLgth2=(*iter)->getMeshLength();
7903       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7904       if(iter!=meshes.begin())
7905         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7906       else
7907         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7908       offset+=meshLgth2;
7909     }
7910   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7911   ret->setName("merge");
7912   ret->setMeshDimension(meshDim);
7913   ret->setConnectivity(nodal,nodalIndex,true);
7914   ret->setCoords(coords);
7915   return ret;
7916 }
7917
7918 /*!
7919  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7920  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7921  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7922  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7923  * New" mode are returned for each input mesh.
7924  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7925  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7926  *          valid values [0,1,2], see zipConnectivityTraducer().
7927  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7928  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7929  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7930  *          no more needed.
7931  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7932  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7933  *          is no more needed.
7934  *  \throw If \a meshes.size() == 0.
7935  *  \throw If \a meshes[ *i* ] == NULL.
7936  *  \throw If the meshes do not share the node coordinates array.
7937  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7938  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7939  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7940  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7941  */
7942 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7943 {
7944   //All checks are delegated to MergeUMeshesOnSameCoords
7945   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7946   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7947   corr.resize(meshes.size());
7948   std::size_t nbOfMeshes=meshes.size();
7949   int offset=0;
7950   const int *o2nPtr=o2n->getConstPointer();
7951   for(std::size_t i=0;i<nbOfMeshes;i++)
7952     {
7953       DataArrayInt *tmp=DataArrayInt::New();
7954       int curNbOfCells=meshes[i]->getNumberOfCells();
7955       tmp->alloc(curNbOfCells,1);
7956       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7957       offset+=curNbOfCells;
7958       tmp->setName(meshes[i]->getName());
7959       corr[i]=tmp;
7960     }
7961   return ret.retn();
7962 }
7963
7964 /*!
7965  * Makes all given meshes share the nodal connectivity array. The common connectivity
7966  * array is created by concatenating the connectivity arrays of all given meshes. All
7967  * the given meshes must be of the same space dimension but dimension of cells **can
7968  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7969  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7970  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7971  *  \param [in,out] meshes - a vector of meshes to update.
7972  *  \throw If any of \a meshes is NULL.
7973  *  \throw If the coordinates array is not set in any of \a meshes.
7974  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7975  *  \throw If \a meshes are of different space dimension.
7976  */
7977 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7978 {
7979   std::size_t sz=meshes.size();
7980   if(sz==0 || sz==1)
7981     return;
7982   std::vector< const DataArrayDouble * > coords(meshes.size());
7983   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7984   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7985     {
7986       if((*it))
7987         {
7988           (*it)->checkConnectivityFullyDefined();
7989           const DataArrayDouble *coo=(*it)->getCoords();
7990           if(coo)
7991             *it2=coo;
7992           else
7993             {
7994               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7995               oss << " has no coordinate array defined !";
7996               throw INTERP_KERNEL::Exception(oss.str().c_str());
7997             }
7998         }
7999       else
8000         {
8001           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8002           oss << " is null !";
8003           throw INTERP_KERNEL::Exception(oss.str().c_str());
8004         }
8005     }
8006   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8007   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8008   int offset=(*it)->getNumberOfNodes();
8009   (*it++)->setCoords(res);
8010   for(;it!=meshes.end();it++)
8011     {
8012       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8013       (*it)->setCoords(res);
8014       (*it)->shiftNodeNumbersInConn(offset);
8015       offset+=oldNumberOfNodes;
8016     }
8017 }
8018
8019 /*!
8020  * Merges nodes coincident with a given precision within all given meshes that share
8021  * the nodal connectivity array. The given meshes **can be of different** mesh
8022  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8023  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8024  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8025  *  \param [in,out] meshes - a vector of meshes to update.
8026  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8027  *  \throw If any of \a meshes is NULL.
8028  *  \throw If the \a meshes do not share the same node coordinates array.
8029  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8030  */
8031 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8032 {
8033   if(meshes.empty())
8034     return ;
8035   std::set<const DataArrayDouble *> s;
8036   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8037     {
8038       if(*it)
8039         s.insert((*it)->getCoords());
8040       else
8041         {
8042           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 !";
8043           throw INTERP_KERNEL::Exception(oss.str().c_str());
8044         }
8045     }
8046   if(s.size()!=1)
8047     {
8048       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 !";
8049       throw INTERP_KERNEL::Exception(oss.str().c_str());
8050     }
8051   const DataArrayDouble *coo=*(s.begin());
8052   if(!coo)
8053     return;
8054   //
8055   DataArrayInt *comm,*commI;
8056   coo->findCommonTuples(eps,-1,comm,commI);
8057   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8058   int oldNbOfNodes=coo->getNumberOfTuples();
8059   int newNbOfNodes;
8060   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8061   if(oldNbOfNodes==newNbOfNodes)
8062     return ;
8063   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8064   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8065     {
8066       (*it)->renumberNodesInConn(o2n->getConstPointer());
8067       (*it)->setCoords(newCoords);
8068     } 
8069 }
8070
8071 /*!
8072  * 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.
8073  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8074  * \param isQuad specifies the policy of connectivity.
8075  * @ret in/out parameter in which the result will be append
8076  */
8077 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8078 {
8079   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8080   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8081   ret.push_back(cm.getExtrudedType());
8082   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8083   switch(flatType)
8084   {
8085     case INTERP_KERNEL::NORM_POINT1:
8086       {
8087         ret.push_back(connBg[1]);
8088         ret.push_back(connBg[1]+nbOfNodesPerLev);
8089         break;
8090       }
8091     case INTERP_KERNEL::NORM_SEG2:
8092       {
8093         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8094         ret.insert(ret.end(),conn,conn+4);
8095         break;
8096       }
8097     case INTERP_KERNEL::NORM_SEG3:
8098       {
8099         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8100         ret.insert(ret.end(),conn,conn+8);
8101         break;
8102       }
8103     case INTERP_KERNEL::NORM_QUAD4:
8104       {
8105         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8106         ret.insert(ret.end(),conn,conn+8);
8107         break;
8108       }
8109     case INTERP_KERNEL::NORM_TRI3:
8110       {
8111         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8112         ret.insert(ret.end(),conn,conn+6);
8113         break;
8114       }
8115     case INTERP_KERNEL::NORM_TRI6:
8116       {
8117         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,
8118           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8119         ret.insert(ret.end(),conn,conn+15);
8120         break;
8121       }
8122     case INTERP_KERNEL::NORM_QUAD8:
8123       {
8124         int conn[20]={
8125           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8126           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8127           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8128         };
8129         ret.insert(ret.end(),conn,conn+20);
8130         break;
8131       }
8132     case INTERP_KERNEL::NORM_POLYGON:
8133       {
8134         std::back_insert_iterator< std::vector<int> > ii(ret);
8135         std::copy(connBg+1,connEnd,ii);
8136         *ii++=-1;
8137         std::reverse_iterator<const int *> rConnBg(connEnd);
8138         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8139         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8140         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8141         for(std::size_t i=0;i<nbOfRadFaces;i++)
8142           {
8143             *ii++=-1;
8144             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8145             std::copy(conn,conn+4,ii);
8146           }
8147         break;
8148       }
8149     default:
8150       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8151   }
8152 }
8153
8154 /*!
8155  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8156  */
8157 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8158 {
8159   std::size_t i, ip1;
8160   double v[3]={0.,0.,0.};
8161   std::size_t sz=std::distance(begin,end);
8162   if(isQuadratic)
8163     sz/=2;
8164   for(i=0;i<sz;i++)
8165     {
8166       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];
8167       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8168       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8169     }
8170   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8171
8172   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8173   // SEG3 forming a circle):
8174   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8175     {
8176       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8177       for(std::size_t j=0;j<sz;j++)
8178         {
8179           if (j%2)  // current point i is quadratic, next point i+1 is standard
8180             {
8181               i = sz+j;
8182               ip1 = (j+1)%sz; // ip1 = "i+1"
8183             }
8184           else      // current point i is standard, next point i+1 is quadratic
8185             {
8186               i = j;
8187               ip1 = j+sz;
8188             }
8189           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8190           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8191           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8192         }
8193       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8194     }
8195   return (ret>0.);
8196 }
8197
8198 /*!
8199  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8200  */
8201 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8202 {
8203   std::vector<std::pair<int,int> > edges;
8204   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8205   const int *bgFace=begin;
8206   for(std::size_t i=0;i<nbOfFaces;i++)
8207     {
8208       const int *endFace=std::find(bgFace+1,end,-1);
8209       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8210       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8211         {
8212           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8213           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8214             return false;
8215           edges.push_back(p1);
8216         }
8217       bgFace=endFace+1;
8218     }
8219   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8220 }
8221
8222 /*!
8223  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8224  */
8225 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8226 {
8227   double vec0[3],vec1[3];
8228   std::size_t sz=std::distance(begin,end);
8229   if(sz%2!=0)
8230     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8231   int nbOfNodes=(int)sz/2;
8232   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8233   const double *pt0=coords+3*begin[0];
8234   const double *pt1=coords+3*begin[nbOfNodes];
8235   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8236   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8237 }
8238
8239 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8240 {
8241   std::size_t sz=std::distance(begin,end);
8242   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8243   std::size_t nbOfNodes(sz/2);
8244   std::copy(begin,end,(int *)tmp);
8245   for(std::size_t j=1;j<nbOfNodes;j++)
8246     {
8247       begin[j]=tmp[nbOfNodes-j];
8248       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8249     }
8250 }
8251
8252 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8253 {
8254   std::size_t sz=std::distance(begin,end);
8255   if(sz!=4)
8256     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8257   double vec0[3],vec1[3];
8258   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8259   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]; 
8260   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;
8261 }
8262
8263 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8264 {
8265   std::size_t sz=std::distance(begin,end);
8266   if(sz!=5)
8267     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8268   double vec0[3];
8269   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8270   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8271   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8272 }
8273
8274 /*!
8275  * 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 ) 
8276  * 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
8277  * a 2D space.
8278  *
8279  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8280  * \param [in] coords the coordinates with nb of components exactly equal to 3
8281  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8282  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8283  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8284  */
8285 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8286 {
8287   int nbFaces=std::count(begin+1,end,-1)+1;
8288   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8289   double *vPtr=v->getPointer();
8290   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8291   double *pPtr=p->getPointer();
8292   const int *stFaceConn=begin+1;
8293   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8294     {
8295       const int *endFaceConn=std::find(stFaceConn,end,-1);
8296       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8297       stFaceConn=endFaceConn+1;
8298     }
8299   pPtr=p->getPointer(); vPtr=v->getPointer();
8300   DataArrayInt *comm1=0,*commI1=0;
8301   v->findCommonTuples(eps,-1,comm1,commI1);
8302   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8303   const int *comm1Ptr=comm1->getConstPointer();
8304   const int *commI1Ptr=commI1->getConstPointer();
8305   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8306   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8307   //
8308   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8309   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8310   mm->finishInsertingCells();
8311   //
8312   for(int i=0;i<nbOfGrps1;i++)
8313     {
8314       int vecId=comm1Ptr[commI1Ptr[i]];
8315       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8316       DataArrayInt *comm2=0,*commI2=0;
8317       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8318       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8319       const int *comm2Ptr=comm2->getConstPointer();
8320       const int *commI2Ptr=commI2->getConstPointer();
8321       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8322       for(int j=0;j<nbOfGrps2;j++)
8323         {
8324           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8325             {
8326               res->insertAtTheEnd(begin,end);
8327               res->pushBackSilent(-1);
8328             }
8329           else
8330             {
8331               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8332               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8333               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8334               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8335               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8336               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8337               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8338               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8339               const int *idsNodePtr=idsNode->getConstPointer();
8340               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];
8341               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8342               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8343               if(std::abs(norm)>eps)
8344                 {
8345                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8346                   mm3->rotate(center,vec,angle);
8347                 }
8348               mm3->changeSpaceDimension(2);
8349               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8350               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8351               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8352               int nbOfCells=mm4->getNumberOfCells();
8353               for(int k=0;k<nbOfCells;k++)
8354                 {
8355                   int l=0;
8356                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8357                     res->pushBackSilent(idsNodePtr[*work]);
8358                   res->pushBackSilent(-1);
8359                 }
8360             }
8361         }
8362     }
8363   res->popBackSilent();
8364 }
8365
8366 /*!
8367  * 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
8368  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8369  * 
8370  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8371  * \param [in] coords coordinates expected to have 3 components.
8372  * \param [in] begin start of the nodal connectivity of the face.
8373  * \param [in] end end of the nodal connectivity (excluded) of the face.
8374  * \param [out] v the normalized vector of size 3
8375  * \param [out] p the pos of plane
8376  */
8377 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8378 {
8379   std::size_t nbPoints=std::distance(begin,end);
8380   if(nbPoints<3)
8381     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8382   double vec[3]={0.,0.,0.};
8383   std::size_t j=0;
8384   bool refFound=false;
8385   for(;j<nbPoints-1 && !refFound;j++)
8386     {
8387       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8388       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8389       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8390       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8391       if(norm>eps)
8392         {
8393           refFound=true;
8394           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8395         }
8396     }
8397   for(std::size_t i=j;i<nbPoints-1;i++)
8398     {
8399       double curVec[3];
8400       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8401       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8402       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8403       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8404       if(norm<eps)
8405         continue;
8406       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8407       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];
8408       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8409       if(norm>eps)
8410         {
8411           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8412           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8413           return ;
8414         }
8415     }
8416   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8417 }
8418
8419 /*!
8420  * This method tries to obtain a well oriented polyhedron.
8421  * If the algorithm fails, an exception will be thrown.
8422  */
8423 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8424 {
8425   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8426   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8427   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8428   isPerm[0]=true;
8429   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8430   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8431   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8432   //
8433   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8434     {
8435       bgFace=begin;
8436       std::size_t smthChanged=0;
8437       for(std::size_t i=0;i<nbOfFaces;i++)
8438         {
8439           endFace=std::find(bgFace+1,end,-1);
8440           nbOfEdgesInFace=std::distance(bgFace,endFace);
8441           if(!isPerm[i])
8442             {
8443               bool b;
8444               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8445                 {
8446                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8447                   std::pair<int,int> p2(p1.second,p1.first);
8448                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8449                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8450                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8451                 }
8452               if(isPerm[i])
8453                 { 
8454                   if(!b)
8455                     std::reverse(bgFace+1,endFace);
8456                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8457                     {
8458                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8459                       std::pair<int,int> p2(p1.second,p1.first);
8460                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8461                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8462                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8463                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8464                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8465                       if(it!=edgesOK.end())
8466                         {
8467                           edgesOK.erase(it);
8468                           edgesFinished.push_back(p1);
8469                         }
8470                       else
8471                         edgesOK.push_back(p1);
8472                     }
8473                 }
8474             }
8475           bgFace=endFace+1;
8476         }
8477       if(smthChanged==0)
8478         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8479     }
8480   if(!edgesOK.empty())
8481     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8482   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8483     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8484       bgFace=begin;
8485       for(std::size_t i=0;i<nbOfFaces;i++)
8486         {
8487           endFace=std::find(bgFace+1,end,-1);
8488           std::reverse(bgFace+1,endFace);
8489           bgFace=endFace+1;
8490         }
8491     }
8492 }
8493
8494 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8495 {
8496   int nbOfNodesExpected(skin->getNumberOfNodes());
8497   const int *n2oPtr(n2o->getConstPointer());
8498   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8499   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8500   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8501   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8502   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8503   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8504   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8505   if(nbOfNodesExpected<1)
8506     return ret.retn();
8507   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8508   *work++=n2oPtr[prevNode];
8509   for(int i=1;i<nbOfNodesExpected;i++)
8510     {
8511       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8512         {
8513           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8514           conn.erase(prevNode);
8515           if(conn.size()==1)
8516             {
8517               int curNode(*(conn.begin()));
8518               *work++=n2oPtr[curNode];
8519               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8520               shar.erase(prevCell);
8521               if(shar.size()==1)
8522                 {
8523                   prevCell=*(shar.begin());
8524                   prevNode=curNode;
8525                 }
8526               else
8527                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8528             }
8529           else
8530             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8531         }
8532       else
8533         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8534     }
8535   return ret.retn();
8536 }
8537
8538 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8539 {
8540   int nbOfNodesExpected(skin->getNumberOfNodes());
8541   int nbOfTurn(nbOfNodesExpected/2);
8542   const int *n2oPtr(n2o->getConstPointer());
8543   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8544   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8545   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8546   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8547   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8548   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8549   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8550   if(nbOfNodesExpected<1)
8551     return ret.retn();
8552   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8553   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8554   for(int i=1;i<nbOfTurn;i++)
8555     {
8556       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8557         {
8558           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8559           conn.erase(prevNode);
8560           if(conn.size()==1)
8561             {
8562               int curNode(*(conn.begin()));
8563               *work=n2oPtr[curNode];
8564               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8565               shar.erase(prevCell);
8566               if(shar.size()==1)
8567                 {
8568                   int curCell(*(shar.begin()));
8569                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8570                   prevCell=curCell;
8571                   prevNode=curNode;
8572                   work++;
8573                 }
8574               else
8575                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8576             }
8577           else
8578             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8579         }
8580       else
8581         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8582     }
8583   return ret.retn();
8584 }
8585
8586 /*!
8587  * This method makes the assumption spacedimension == meshdimension == 2.
8588  * This method works only for linear cells.
8589  * 
8590  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8591  */
8592 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8593 {
8594   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8595     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8596   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8597   int oldNbOfNodes(skin->getNumberOfNodes());
8598   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8599   int nbOfNodesExpected(skin->getNumberOfNodes());
8600   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8601   int nbCells(skin->getNumberOfCells());
8602   if(nbCells==nbOfNodesExpected)
8603     return buildUnionOf2DMeshLinear(skin,n2o);
8604   else if(2*nbCells==nbOfNodesExpected)
8605     return buildUnionOf2DMeshQuadratic(skin,n2o);
8606   else
8607     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8608 }
8609
8610 /*!
8611  * This method makes the assumption spacedimension == meshdimension == 3.
8612  * This method works only for linear cells.
8613  * 
8614  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8615  */
8616 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8617 {
8618   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8619     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8620   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8621   const int *conn=m->getNodalConnectivity()->getConstPointer();
8622   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8623   int nbOfCells=m->getNumberOfCells();
8624   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8625   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8626   if(nbOfCells<1)
8627     return ret.retn();
8628   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8629   for(int i=1;i<nbOfCells;i++)
8630     {
8631       *work++=-1;
8632       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8633     }
8634   return ret.retn();
8635 }
8636
8637 /*!
8638  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8639  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8640  */
8641 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8642 {
8643   double *w=zipFrmt;
8644   if(spaceDim==3)
8645     for(int i=0;i<nbOfNodesInCell;i++)
8646       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8647   else if(spaceDim==2)
8648     {
8649       for(int i=0;i<nbOfNodesInCell;i++)
8650         {
8651           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8652           *w++=0.;
8653         }
8654     }
8655   else
8656     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8657 }
8658
8659 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8660 {
8661   int nbOfCells=getNumberOfCells();
8662   if(nbOfCells<=0)
8663     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8664   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};
8665   ofs << "  <" << getVTKDataSetType() << ">\n";
8666   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8667   ofs << "      <PointData>\n" << pointData << std::endl;
8668   ofs << "      </PointData>\n";
8669   ofs << "      <CellData>\n" << cellData << std::endl;
8670   ofs << "      </CellData>\n";
8671   ofs << "      <Points>\n";
8672   if(getSpaceDimension()==3)
8673     _coords->writeVTK(ofs,8,"Points",byteData);
8674   else
8675     {
8676       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8677       coo->writeVTK(ofs,8,"Points",byteData);
8678     }
8679   ofs << "      </Points>\n";
8680   ofs << "      <Cells>\n";
8681   const int *cPtr=_nodal_connec->getConstPointer();
8682   const int *cIPtr=_nodal_connec_index->getConstPointer();
8683   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8684   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8685   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8686   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8687   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8688   int szFaceOffsets=0,szConn=0;
8689   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8690     {
8691       *w2=cPtr[cIPtr[i]];
8692       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8693         {
8694           *w1=-1;
8695           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8696           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8697         }
8698       else
8699         {
8700           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8701           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8702           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8703           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8704           w4=std::copy(c.begin(),c.end(),w4);
8705         }
8706     }
8707   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8708   types->writeVTK(ofs,8,"UInt8","types",byteData);
8709   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8710   if(szFaceOffsets!=0)
8711     {//presence of Polyhedra
8712       connectivity->reAlloc(szConn);
8713       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8714       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8715       w1=faces->getPointer();
8716       for(int i=0;i<nbOfCells;i++)
8717         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8718           {
8719             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8720             *w1++=nbFaces;
8721             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8722             for(int j=0;j<nbFaces;j++)
8723               {
8724                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8725                 *w1++=(int)std::distance(w6,w5);
8726                 w1=std::copy(w6,w5,w1);
8727                 w6=w5+1;
8728               }
8729           }
8730       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8731     }
8732   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8733   ofs << "      </Cells>\n";
8734   ofs << "    </Piece>\n";
8735   ofs << "  </" << getVTKDataSetType() << ">\n";
8736 }
8737
8738 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8739 {
8740   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8741   if(_mesh_dim==-2)
8742     { stream << " Not set !"; return ; }
8743   stream << " Mesh dimension : " << _mesh_dim << ".";
8744   if(_mesh_dim==-1)
8745     return ;
8746   if(!_coords)
8747     { stream << " No coordinates set !"; return ; }
8748   if(!_coords->isAllocated())
8749     { stream << " Coordinates set but not allocated !"; return ; }
8750   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8751   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8752   if(!_nodal_connec_index)
8753     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8754   if(!_nodal_connec_index->isAllocated())
8755     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8756   int lgth=_nodal_connec_index->getNumberOfTuples();
8757   int cpt=_nodal_connec_index->getNumberOfComponents();
8758   if(cpt!=1 || lgth<1)
8759     return ;
8760   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8761 }
8762
8763 std::string MEDCouplingUMesh::getVTKDataSetType() const
8764 {
8765   return std::string("UnstructuredGrid");
8766 }
8767
8768 std::string MEDCouplingUMesh::getVTKFileExtension() const
8769 {
8770   return std::string("vtu");
8771 }
8772
8773 /*!
8774  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8775  * returns a result mesh constituted by polygons.
8776  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8777  * all nodes from m2.
8778  * The meshes should be in 2D space. In
8779  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8780  * meshes.
8781  *  \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
8782  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8783  *  \param [in] 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
8784  *                      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)
8785  *  \param [in] eps - precision used to detect coincident mesh entities.
8786  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8787  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8788  *         this array using decrRef() as it is no more needed.
8789  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8790  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8791  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8792  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8793  *         it is no more needed.  
8794  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8795  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8796  *         is no more needed.  
8797  *  \throw If the coordinates array is not set in any of the meshes.
8798  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8799  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8800  *
8801  *  \sa conformize2D, mergeNodes
8802  */
8803 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8804                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8805 {
8806   if(!m1 || !m2)
8807     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8808   m1->checkFullyDefined();
8809   m2->checkFullyDefined();
8810   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8811     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8812
8813   // Step 1: compute all edge intersections (new nodes)
8814   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8815   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8816   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8817   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8818   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8819                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8820                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8821   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8823   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8824
8825   // Step 2: re-order newly created nodes according to the ordering found in m2
8826   std::vector< std::vector<int> > intersectEdge2;
8827   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8828   subDiv2.clear(); dd5=0; dd6=0;
8829
8830   // Step 3:
8831   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8832   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8833   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8834                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8835
8836   // Step 4: Prepare final result:
8837   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8838   addCooDa->alloc((int)(addCoo.size())/2,2);
8839   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8840   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8841   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8842   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8843   std::vector<const DataArrayDouble *> coordss(4);
8844   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8845   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8846   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8847   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8848   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8849   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8850   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8851   ret->setConnectivity(conn,connI,true);
8852   ret->setCoords(coo);
8853   cellNb1=c1.retn(); cellNb2=c2.retn();
8854   return ret.retn();
8855 }
8856
8857 /// @cond INTERNAL
8858
8859 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8860 {
8861   if(candidates.empty())
8862     return false;
8863   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8864     {
8865       const std::vector<int>& pool(intersectEdge1[*it]);
8866       int tmp[2]; tmp[0]=start; tmp[1]=stop;
8867       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8868         {
8869           retVal=*it+1;
8870           return true;
8871         }
8872       tmp[0]=stop; tmp[1]=start;
8873       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8874         {
8875           retVal=-*it-1;
8876           return true;
8877         }
8878     }
8879   return false;
8880 }
8881
8882 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,
8883                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8884 {
8885   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8886   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8887   int nCells(mesh1D->getNumberOfCells());
8888   if(nCells!=(int)intersectEdge2.size())
8889     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8890   const DataArrayDouble *coo2(mesh1D->getCoords());
8891   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8892   const double *coo2Ptr(coo2->begin());
8893   int offset1(coords1->getNumberOfTuples());
8894   int offset2(offset1+coo2->getNumberOfTuples());
8895   int offset3(offset2+addCoo.size()/2);
8896   std::vector<double> addCooQuad;
8897   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8898   int tmp[4],cicnt(0),kk(0);
8899   for(int i=0;i<nCells;i++)
8900     {
8901       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8902       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8903       const std::vector<int>& subEdges(intersectEdge2[i]);
8904       int nbSubEdge(subEdges.size()/2);
8905       for(int j=0;j<nbSubEdge;j++,kk++)
8906         {
8907           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));
8908           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8909           INTERP_KERNEL::Edge *e2Ptr(e2);
8910           std::map<int,int>::const_iterator itm;
8911           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8912             {
8913               tmp[0]=INTERP_KERNEL::NORM_SEG3;
8914               itm=mergedNodes.find(subEdges[2*j]);
8915               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8916               itm=mergedNodes.find(subEdges[2*j+1]);
8917               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8918               tmp[3]=offset3+(int)addCooQuad.size()/2;
8919               double tmp2[2];
8920               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8921               cicnt+=4;
8922               cOut->insertAtTheEnd(tmp,tmp+4);
8923               ciOut->pushBackSilent(cicnt);
8924             }
8925           else
8926             {
8927               tmp[0]=INTERP_KERNEL::NORM_SEG2;
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               cicnt+=3;
8933               cOut->insertAtTheEnd(tmp,tmp+3);
8934               ciOut->pushBackSilent(cicnt);
8935             }
8936           int tmp00;
8937           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8938             {
8939               idsInRetColinear->pushBackSilent(kk);
8940               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8941             }
8942         }
8943       e->decrRef();
8944     }
8945   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8946   ret->setConnectivity(cOut,ciOut,true);
8947   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8948   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8949   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8950   std::vector<const DataArrayDouble *> coordss(4);
8951   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8952   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8953   ret->setCoords(arr);
8954   return ret.retn();
8955 }
8956
8957 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8958 {
8959   std::vector<int> allEdges;
8960   for(const int *it2(descBg);it2!=descEnd;it2++)
8961     {
8962       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
8963       if(*it2>0)
8964         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8965       else
8966         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8967     }
8968   std::size_t nb(allEdges.size());
8969   if(nb%2!=0)
8970     throw INTERP_KERNEL::Exception("BuildRefined2DCell : internal error 1 !");
8971   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8972   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8973   ret->setCoords(coords);
8974   ret->allocateCells(1);
8975   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
8976   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8977     connOut[kk]=allEdges[2*kk];
8978   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
8979   return ret.retn();
8980 }
8981
8982 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
8983 {
8984   bool isQuad(false);
8985   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
8986     {
8987       const INTERP_KERNEL::Edge *ee(*it);
8988       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
8989         isQuad=true;
8990     }
8991   if(!isQuad)
8992     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
8993   else
8994     {
8995       const double *coo(mesh2D->getCoords()->begin());
8996       std::size_t sz(conn.size());
8997       std::vector<double> addCoo;
8998       std::vector<int> conn2(conn);
8999       int offset(mesh2D->getNumberOfNodes());
9000       for(std::size_t i=0;i<sz;i++)
9001         {
9002           double tmp[2];
9003           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);
9004           addCoo.insert(addCoo.end(),tmp,tmp+2);
9005           conn2.push_back(offset+(int)i);
9006         }
9007       mesh2D->getCoords()->rearrange(1);
9008       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9009       mesh2D->getCoords()->rearrange(2);
9010       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9011     }
9012 }
9013
9014 /*!
9015  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9016  */
9017 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9018                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9019 {
9020   std::size_t nb(edge1Bis.size()/2);
9021   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9022   int iEnd(splitMesh1D->getNumberOfCells());
9023   if(iEnd==0)
9024     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9025   std::size_t ii,jj;
9026   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9027   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9028   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9029   //
9030   if(jj==nb)
9031     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9032       out0.resize(1); out1.resize(1);
9033       std::vector<int>& connOut(out0[0]);
9034       connOut.resize(nbOfEdgesOf2DCellSplit);
9035       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9036       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9037       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9038         {
9039           connOut[kk]=edge1Bis[2*kk];
9040           edgesPtr[kk]=edge1BisPtr[2*kk];
9041         }
9042     }
9043   else
9044     {
9045       // [i,iEnd[ contains the
9046       out0.resize(2); out1.resize(2);
9047       std::vector<int>& connOutLeft(out0[0]);
9048       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9049       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9050       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9051       for(std::size_t k=ii;k<jj+1;k++)
9052         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9053       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9054       for(int ik=iEnd-1;ik>=0;ik--)
9055         {
9056           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9057           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9058           ees[iEnd-1-ik]=ee;
9059         }
9060       for(int ik=iEnd-1;ik>=0;ik--)
9061         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9062       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9063         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9064       eleft.insert(eleft.end(),ees.begin(),ees.end());
9065       for(int ik=0;ik<iEnd;ik++)
9066         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9067       eright.insert(eright.end(),ees.rbegin(),ees.rend());
9068     }
9069 }
9070
9071 /// @endcond
9072
9073 /// @cond INTERNAL
9074
9075 struct CellInfo
9076 {
9077 public:
9078   CellInfo() { }
9079   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9080 public:
9081   std::vector<int> _edges;
9082   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9083 };
9084
9085 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9086 {
9087   std::size_t nbe(edges.size());
9088   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9089   for(std::size_t i=0;i<nbe;i++)
9090     {
9091       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9092       edgesPtr2[2*i]=edgesPtr[i]; edgesPtr2[2*i+1]=edgesPtr[i];
9093     }
9094   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9095   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9096   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9097 }
9098
9099 class EdgeInfo
9100 {
9101 public:
9102   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9103   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9104   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9105   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9106   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9107 private:
9108   int _istart;
9109   int _iend;
9110   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9111   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9112   int _left;
9113   int _right;
9114 };
9115
9116 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9117 {
9118   const MEDCouplingUMesh *mesh(_mesh);
9119   if(mesh)
9120     return ;
9121   if(_right<pos)
9122     return ;
9123   if(_left>pos)
9124     { _left++; _right++; return ; }
9125   if(_right==pos)
9126     {
9127       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9128       if((isLeft && isRight) || (!isLeft && !isRight))
9129         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9130       if(isLeft)
9131         return ;
9132       if(isRight)
9133         {
9134           _right++;
9135           return ;
9136         }
9137     }
9138   if(_left==pos)
9139     {
9140       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9141       if((isLeft && isRight) || (!isLeft && !isRight))
9142         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9143       if(isLeft)
9144         {
9145           _right++;
9146           return ;
9147         }
9148       if(isRight)
9149         {
9150           _left++;
9151           _right++;
9152           return ;
9153         }
9154     }
9155 }
9156
9157 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9158 {
9159   const MEDCouplingUMesh *mesh(_mesh);
9160   if(!mesh)
9161     {
9162       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9163     }
9164   else
9165     {// not fully splitting cell case
9166       if(mesh2D->getNumberOfCells()==1)
9167         {//little optimization. 1 cell no need to find in which cell mesh is !
9168           neighbors[0]=offset; neighbors[1]=offset;
9169           return;
9170         }
9171       else
9172         {
9173           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9174           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9175           if(cellId==-1)
9176             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9177           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9178         }
9179     }
9180 }
9181
9182 class VectorOfCellInfo
9183 {
9184 public:
9185   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9186   std::size_t size() const { return _pool.size(); }
9187   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9188   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);
9189   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9190   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9191   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9192   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9193 private:
9194   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9195   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9196   const CellInfo& get(int pos) const;
9197   CellInfo& get(int pos);
9198 private:
9199   std::vector<CellInfo> _pool;
9200   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9201   std::vector<EdgeInfo> _edge_info;
9202 };
9203
9204 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9205 {
9206   _pool[0]._edges=edges;
9207   _pool[0]._edges_ptr=edgesPtr;
9208 }
9209
9210 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9211 {
9212   if(_pool.empty())
9213     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9214   if(_pool.size()==1)
9215     return 0;
9216   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9217   if(!zeMesh)
9218     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9219   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9220   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9221 }
9222
9223 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)
9224 {
9225   get(pos);//to check pos
9226   bool isFast(pos==0 && _pool.size()==1);
9227   std::size_t sz(edges.size());
9228   // dealing with edges
9229   if(sz==1)
9230     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9231   else
9232     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9233   //
9234   std::vector<CellInfo> pool(_pool.size()-1+sz);
9235   for(int i=0;i<pos;i++)
9236     pool[i]=_pool[i];
9237   for(std::size_t j=0;j<sz;j++)
9238     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9239   for(int i=pos+1;i<(int)_pool.size();i++)
9240     pool[pos+sz-1]=_pool[i];
9241   _pool=pool;
9242   //
9243   if(sz==2)
9244     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9245   //
9246   if(isFast)
9247     {
9248       _ze_mesh=mesh;
9249       return ;
9250     }
9251   //
9252   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9253   if(pos>0)
9254     {
9255       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9256       ms.push_back(elt);
9257     }
9258   ms.push_back(mesh);
9259   if(pos<_ze_mesh->getNumberOfCells()-1)
9260   {
9261     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9262     ms.push_back(elt);
9263   }
9264   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9265   for(std::size_t j=0;j<ms2.size();j++)
9266     ms2[j]=ms[j];
9267   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9268 }
9269
9270 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9271 {
9272   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9273 }
9274
9275 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9276 {
9277   if(pos<0)
9278     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9279   int ret(0);
9280   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9281     {
9282       if((*it).isInMyRange(pos))
9283         return ret;
9284     }
9285   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9286 }
9287
9288 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9289 {
9290   get(pos);//to check;
9291   if(_edge_info.empty())
9292     return ;
9293   std::size_t sz(_edge_info.size()-1);
9294   for(std::size_t i=0;i<sz;i++)
9295     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9296 }
9297
9298 const CellInfo& VectorOfCellInfo::get(int pos) const
9299 {
9300   if(pos<0 || pos>=(int)_pool.size())
9301     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9302   return _pool[pos];
9303 }
9304
9305 CellInfo& VectorOfCellInfo::get(int pos)
9306 {
9307   if(pos<0 || pos>=(int)_pool.size())
9308     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9309   return _pool[pos];
9310 }
9311
9312 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9313                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9314 {
9315   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9316   if(nbCellsInSplitMesh1D==0)
9317     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9318   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9319   std::size_t nb(allEdges.size()),jj;
9320   if(nb%2!=0)
9321     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9322   std::vector<int> edge1Bis(nb*2);
9323   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9324   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9325   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9326   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9327   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9328   //
9329   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9330   int *idsLeftRightPtr(idsLeftRight->getPointer());
9331   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9332   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9333     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9334       int iEnd(iStart);
9335       for(;iEnd<nbCellsInSplitMesh1D;)
9336         {
9337           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9338           if(jj!=nb)
9339             break;
9340           else
9341             iEnd++;
9342         }
9343       if(iEnd<nbCellsInSplitMesh1D)
9344         iEnd++;
9345       //
9346       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9347       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9348       //
9349       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9350       retTmp->setCoords(splitMesh1D->getCoords());
9351       retTmp->allocateCells();
9352
9353       std::vector< std::vector<int> > out0;
9354       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9355
9356       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9357       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9358         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9359       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9360       //
9361       iStart=iEnd;
9362     }
9363   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9364     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9365   return pool.getZeMesh().retn();
9366 }
9367
9368 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9369                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9370                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9371 {
9372   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9373   //
9374   std::vector<int> allEdges;
9375   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr;
9376   for(const int *it(descBg);it!=descEnd;it++)
9377     {
9378       int edgeId(std::abs(*it)-1);
9379       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9380       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9381       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9382       if(*it>0)
9383         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9384       else
9385         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9386       std::size_t sz(edge1.size());
9387       for(std::size_t cnt=0;cnt<sz;cnt++)
9388         allEdgesPtr.push_back(ee);
9389     }
9390   //
9391   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9392 }
9393
9394 /// @endcond
9395
9396 /*!
9397  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9398  * 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
9399  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9400  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9401  *
9402  * \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
9403  *                      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)
9404  * \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
9405  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9406  * \param [in] eps - precision used to perform intersections and localization operations.
9407  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9408  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9409  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9410  *                               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.
9411  * \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
9412  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9413  *                               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.
9414  *
9415  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9416  */
9417 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9418 {
9419   if(!mesh2D || !mesh1D)
9420     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9421   mesh2D->checkFullyDefined();
9422   mesh1D->checkFullyDefined();
9423   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9424   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9425     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9426   // Step 1: compute all edge intersections (new nodes)
9427   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9428   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9429   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9430   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9431   //
9432   // Build desc connectivity
9433   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9434   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9435   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9436   std::map<int,int> mergedNodes;
9437   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9438   // use mergeNodes to fix intersectEdge1
9439   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9440     {
9441       std::size_t n((*it0).size()/2);
9442       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9443       std::map<int,int>::const_iterator it1;
9444       it1=mergedNodes.find(eltStart);
9445       if(it1!=mergedNodes.end())
9446         (*it0)[0]=(*it1).second;
9447       it1=mergedNodes.find(eltEnd);
9448       if(it1!=mergedNodes.end())
9449         (*it0)[2*n-1]=(*it1).second;
9450     }
9451   //
9452   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9453   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9454   // Step 2: re-order newly created nodes according to the ordering found in m2
9455   std::vector< std::vector<int> > intersectEdge2;
9456   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9457   subDiv2.clear();
9458   // Step 3: compute splitMesh1D
9459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9461   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9462       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9463   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(-1); ret3->rearrange(2);
9464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9465   // deal with cells in mesh2D that are not cut but only some of their edges are
9466   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9467   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9468   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9469   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
9470   if(!idsInDesc2DToBeRefined->empty())
9471     {
9472       DataArrayInt *out0(0),*outi0(0);
9473       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9474       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9475       out0s=out0;
9476       out0s=out0s->buildUnique();
9477       out0s->sort(true);
9478     }
9479   //
9480   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9481   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9482   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9483   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9484   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9485   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9486   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9487     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9488   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9489   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9490   if((DataArrayInt *)out0s)
9491     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9492   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9493   // OK all is ready to insert in ret2 mesh
9494   if(!untouchedCells->empty())
9495     {// the most easy part, cells in mesh2D not impacted at all
9496       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9497       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9498       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9499     }
9500   if((DataArrayInt *)out0s)
9501     {// here dealing with cells in out0s but not in cellsToBeModified
9502       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9503       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9504       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9505         {
9506           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9507         }
9508       int offset(ret2->getNumberOfTuples());
9509       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9510       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9511       partOfRet3->fillWithValue(-1); partOfRet3->rearrange(2);
9512       int kk(0),*ret3ptr(partOfRet3->getPointer());
9513       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9514         {
9515           int faceId(std::abs(*it)-1);
9516           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9517             {
9518               int tmp(fewModifiedCells->locateValue(*it2));
9519               if(tmp!=-1)
9520                 {
9521                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9522                     ret3ptr[2*kk]=tmp+offset;
9523                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9524                     ret3ptr[2*kk+1]=tmp+offset;
9525                 }
9526               else
9527                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : internal error 1 !");
9528             }
9529         }
9530       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9531     }
9532   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9533     {
9534       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9535       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9536       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9537       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9538       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9539       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));
9540       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9541       outMesh2DSplit.push_back(splitOfOneCell);
9542       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9543         ret2->pushBackSilent(*it);
9544     }
9545   //
9546   std::size_t nbOfMeshes(outMesh2DSplit.size());
9547   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9548   for(std::size_t i=0;i<nbOfMeshes;i++)
9549     tmp[i]=outMesh2DSplit[i];
9550   //
9551   ret1->getCoords()->setInfoOnComponents(compNames);
9552   //
9553   splitMesh1D=ret1.retn();
9554   splitMesh2D=MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp);
9555   cellIdInMesh2D=ret2.retn();
9556   cellIdInMesh1D=ret3.retn();
9557 }
9558
9559 /**
9560  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9561  * (newly created) nodes corresponding to the edge intersections.
9562  * Output params:
9563  * @param[out] cr, crI connectivity of the resulting mesh
9564  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9565  * TODO: describe input parameters
9566  */
9567 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9568                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9569                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9570                                                          const std::vector<double>& addCoords,
9571                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9572 {
9573   static const int SPACEDIM=2;
9574   const double *coo1(m1->getCoords()->getConstPointer());
9575   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9576   int offset1(m1->getNumberOfNodes());
9577   const double *coo2(m2->getCoords()->getConstPointer());
9578   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9579   int offset2(offset1+m2->getNumberOfNodes());
9580   int offset3(offset2+((int)addCoords.size())/2);
9581   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9582   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9583   // Here a BBTree on 2D-cells, not on segments:
9584   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9585   int ncell1(m1->getNumberOfCells());
9586   crI.push_back(0);
9587   for(int i=0;i<ncell1;i++)
9588     {
9589       std::vector<int> candidates2;
9590       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9591       std::map<INTERP_KERNEL::Node *,int> mapp;
9592       std::map<int,INTERP_KERNEL::Node *> mappRev;
9593       INTERP_KERNEL::QuadraticPolygon pol1;
9594       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9595       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9596       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9597       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9598       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9599       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9600           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9601       //
9602       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
9603       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9604       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9605       for(it1.first();!it1.finished();it1.next())
9606         edges1.insert(it1.current()->getPtr());
9607       //
9608       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9609       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9610       int ii=0;
9611       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9612         {
9613           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9614           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9615           // Complete mapping with elements coming from the current cell it2 in mesh2:
9616           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9617           // pol2 is the new QP in the final merged result.
9618           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9619               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9620         }
9621       ii=0;
9622       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9623         {
9624           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9625           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9626           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9627           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9628         }
9629       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9630       // by m2 but that we still want to keep in the final result.
9631       if(!edges1.empty())
9632         {
9633           try
9634           {
9635               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9636           }
9637           catch(INTERP_KERNEL::Exception& e)
9638           {
9639               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();
9640               throw INTERP_KERNEL::Exception(oss.str().c_str());
9641           }
9642         }
9643       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9644         (*it).second->decrRef();
9645     }
9646 }
9647
9648 /**
9649  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9650  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9651  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9652  * The caller is to deal with the resulting DataArrayInt.
9653  *  \throw If the coordinate array is not set.
9654  *  \throw If the nodal connectivity of the cells is not defined.
9655  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9656  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9657  *
9658  * \sa DataArrayInt::sortEachPairToMakeALinkedList
9659  */
9660 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9661 {
9662   checkFullyDefined();
9663   if(getMeshDimension()!=1)
9664     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9665
9666   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9667   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9668   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9669   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9670   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9671   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9672   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9673   const int * dsi(_dsi->getConstPointer());
9674   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9675   m_points=0;
9676   if (dsii->getNumberOfTuples())
9677     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9678
9679   int nc(getNumberOfCells());
9680   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9681   result->alloc(nc,1);
9682
9683   // set of edges not used so far
9684   std::set<int> edgeSet;
9685   for (int i=0; i<nc; edgeSet.insert(i), i++);
9686
9687   int startSeg=0;
9688   int newIdx=0;
9689   // while we have points with only one neighbor segments
9690   do
9691     {
9692       std::list<int> linePiece;
9693       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9694       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9695         {
9696           // Fill the list forward (resp. backward) from the start segment:
9697           int activeSeg = startSeg;
9698           int prevPointId = -20;
9699           int ptId;
9700           while (!edgeSet.empty())
9701             {
9702               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9703                 {
9704                   if (direction==0)
9705                     linePiece.push_back(activeSeg);
9706                   else
9707                     linePiece.push_front(activeSeg);
9708                   edgeSet.erase(activeSeg);
9709                 }
9710
9711               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9712               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9713               if (dsi[ptId] == 1) // hitting the end of the line
9714                 break;
9715               prevPointId = ptId;
9716               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9717               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9718             }
9719         }
9720       // Done, save final piece into DA:
9721       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9722       newIdx += linePiece.size();
9723
9724       // identify next valid start segment (one which is not consumed)
9725       if(!edgeSet.empty())
9726         startSeg = *(edgeSet.begin());
9727     }
9728   while (!edgeSet.empty());
9729   return result.retn();
9730 }
9731
9732 /// @cond INTERNAL
9733
9734 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9735 {
9736   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9737   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9738   if(it==m.end())
9739     throw INTERP_KERNEL::Exception("Internal error in remapping !");
9740   int v((*it).second);
9741   if(v==forbVal0 || v==forbVal1)
9742     return ;
9743   if(std::find(isect.begin(),isect.end(),v)==isect.end())
9744     isect.push_back(v);
9745 }
9746
9747 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9748 {
9749   int sz(c.size());
9750   if(sz<=1)
9751     return false;
9752   bool presenceOfOn(false);
9753   for(int i=0;i<sz;i++)
9754     {
9755       INTERP_KERNEL::ElementaryEdge *e(c[i]);
9756       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9757         continue ;
9758       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9759       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9760     }
9761   return presenceOfOn;
9762 }
9763
9764 /// @endcond
9765
9766 /**
9767  * 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.
9768  * 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.
9769  * 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.
9770  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
9771  *
9772  * \return int - the number of new nodes created (in most of cases 0).
9773  * 
9774  * \throw If \a this is not coherent.
9775  * \throw If \a this has not spaceDim equal to 2.
9776  * \throw If \a this has not meshDim equal to 2.
9777  * \throw If some subcells needed to be split are orphan.
9778  * \sa MEDCouplingUMesh::conformize2D
9779  */
9780 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9781 {
9782   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9783     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9784   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9785   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9786     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9787   if(midOpt==0 && midOptI==0)
9788     {
9789       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
9790       return 0;
9791     }
9792   else if(midOpt!=0 && midOptI!=0)
9793     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
9794   else
9795     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
9796 }
9797
9798 /*!
9799  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
9800  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
9801  * 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
9802  * 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).
9803  * 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.
9804  * 
9805  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
9806  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
9807  *
9808  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
9809  * This method expects that all nodes in \a this are not closer than \a eps.
9810  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
9811  * 
9812  * \param [in] eps the relative error to detect merged edges.
9813  * \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
9814  *                           that the user is expected to deal with.
9815  *
9816  * \throw If \a this is not coherent.
9817  * \throw If \a this has not spaceDim equal to 2.
9818  * \throw If \a this has not meshDim equal to 2.
9819  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
9820  */
9821 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
9822 {
9823   static const int SPACEDIM=2;
9824   checkCoherency();
9825   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9826     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9827   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
9828   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
9829   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
9830   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
9831   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
9832   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
9833   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
9834   std::vector<double> addCoo;
9835   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
9836   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9837   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9838   for(int i=0;i<nDescCell;i++)
9839     {
9840       std::vector<int> candidates;
9841       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
9842       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9843         if(*it>i)
9844           {
9845             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9846             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
9847                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
9848             INTERP_KERNEL::MergePoints merge;
9849             INTERP_KERNEL::QuadraticPolygon c1,c2;
9850             e1->intersectWith(e2,merge,c1,c2);
9851             e1->decrRef(); e2->decrRef();
9852             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
9853               overlapEdge[i].push_back(*it);
9854             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
9855               overlapEdge[*it].push_back(i);
9856           }
9857     }
9858   // splitting done. sort intersect point in intersectEdge.
9859   std::vector< std::vector<int> > middle(nDescCell);
9860   int nbOf2DCellsToBeSplit(0);
9861   bool middleNeedsToBeUsed(false);
9862   std::vector<bool> cells2DToTreat(nDescCell,false);
9863   for(int i=0;i<nDescCell;i++)
9864     {
9865       std::vector<int>& isect(intersectEdge[i]);
9866       int sz((int)isect.size());
9867       if(sz>1)
9868         {
9869           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9870           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
9871           e->sortSubNodesAbs(coords,isect);
9872           e->decrRef();
9873         }
9874       if(sz!=0)
9875         {
9876           int idx0(rdi[i]),idx1(rdi[i+1]);
9877           if(idx1-idx0!=1)
9878             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
9879           if(!cells2DToTreat[rd[idx0]])
9880             {
9881               cells2DToTreat[rd[idx0]]=true;
9882               nbOf2DCellsToBeSplit++;
9883             }
9884           // try to reuse at most eventual 'middle' of SEG3
9885           std::vector<int>& mid(middle[i]);
9886           mid.resize(sz+1,-1);
9887           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
9888             {
9889               middleNeedsToBeUsed=true;
9890               const std::vector<int>& candidates(overlapEdge[i]);
9891               std::vector<int> trueCandidates;
9892               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
9893                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
9894                   trueCandidates.push_back(*itc);
9895               int stNode(c[ci[i]+1]),endNode(isect[0]);
9896               for(int j=0;j<sz+1;j++)
9897                 {
9898                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
9899                     {
9900                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
9901                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
9902                         { mid[j]=*itc; break; }
9903                     }
9904                   stNode=endNode;
9905                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
9906                 }
9907             }
9908         }
9909     }
9910   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
9911   if(nbOf2DCellsToBeSplit==0)
9912     return ret.retn();
9913   //
9914   int *retPtr(ret->getPointer());
9915   for(int i=0;i<nCell;i++)
9916     if(cells2DToTreat[i])
9917       *retPtr++=i;
9918   //
9919   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
9920   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
9921   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
9922   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
9923   if(middleNeedsToBeUsed)
9924     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
9925   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
9926   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
9927   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.
9928   setPartOfMySelf(ret->begin(),ret->end(),*modif);
9929   {
9930     bool areNodesMerged; int newNbOfNodes;
9931     if(nbOfNodesCreated!=0)
9932       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
9933   }
9934   return ret.retn();
9935 }
9936
9937 /*!
9938  * 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.
9939  * 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).
9940  * 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
9941  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
9942  * 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
9943  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
9944  *
9945  * 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
9946  * using new instance, idem for coordinates.
9947  *
9948  * 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.
9949  * 
9950  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
9951  *
9952  * \throw If \a this is not coherent.
9953  * \throw If \a this has not spaceDim equal to 2.
9954  * \throw If \a this has not meshDim equal to 2.
9955  * 
9956  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9957  */
9958 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9959 {
9960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9961   checkCoherency();
9962   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9963     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9964   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9965   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9966   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9967   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9968   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9969   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9970   const double *coords(_coords->begin());
9971   int *newciptr(newci->getPointer());
9972   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9973     {
9974       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9975         ret->pushBackSilent(i);
9976       newciptr[1]=newc->getNumberOfTuples();
9977     }
9978   //
9979   if(ret->empty())
9980     return ret.retn();
9981   if(!appendedCoords->empty())
9982     {
9983       appendedCoords->rearrange(2);
9984       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9985       //non const part
9986       setCoords(newCoords);
9987     }
9988   //non const part
9989   setConnectivity(newc,newci,true);
9990   return ret.retn();
9991 }
9992
9993 /*!
9994  * \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.
9995  *                               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.
9996  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
9997  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
9998  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
9999  * \param [out] addCoo - nodes to be append at the end
10000  * \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.
10001  */
10002 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10003                                          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)
10004 {
10005   static const int SPACEDIM=2;
10006   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10007   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10008   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10009   // Build BB tree of all edges in the tool mesh (second mesh)
10010   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10011   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10012   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10013   intersectEdge1.resize(nDescCell1);
10014   colinear2.resize(nDescCell2);
10015   subDiv2.resize(nDescCell2);
10016   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10017
10018   std::vector<int> candidates1(1);
10019   int offset1(m1Desc->getNumberOfNodes());
10020   int offset2(offset1+m2Desc->getNumberOfNodes());
10021   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10022     {
10023       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10024       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10025       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10026         {
10027           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10028           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10029           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10030           candidates1[0]=i;
10031           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10032           // 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
10033           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10034           std::set<INTERP_KERNEL::Node *> nodes;
10035           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10036           std::size_t szz(nodes.size());
10037           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10038           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10039           for(std::size_t iii=0;iii<szz;iii++,itt++)
10040             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10041           // end of protection
10042           // Performs egde cutting:
10043           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10044           delete pol2;
10045           delete pol1;
10046         }
10047       else
10048         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10049         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10050     }
10051 }
10052
10053 /*!
10054  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10055  * It builds the descending connectivity of the two meshes, and then using a binary tree
10056  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10057  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10058  */
10059 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10060                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10061                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10062                                                    std::vector<double>& addCoo,
10063                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10064 {
10065   // Build desc connectivity
10066   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10067   desc2=DataArrayInt::New();
10068   descIndx2=DataArrayInt::New();
10069   revDesc2=DataArrayInt::New();
10070   revDescIndx2=DataArrayInt::New();
10071   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10072   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10073   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10074   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10075   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10076   std::map<int,int> notUsedMap;
10077   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10078   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10079   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10080 }
10081
10082 /*!
10083  * This method performs the 2nd step of Partition of 2D mesh.
10084  * This method has 4 inputs :
10085  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10086  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10087  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10088  * 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'
10089  * Nodes end up lying consecutively on a cutted edge.
10090  * \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.
10091  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10092  * \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.
10093  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10094  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10095  */
10096 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10097                                            const std::vector<double>& addCoo,
10098                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10099 {
10100   int offset1=m1->getNumberOfNodes();
10101   int ncell=m2->getNumberOfCells();
10102   const int *c=m2->getNodalConnectivity()->getConstPointer();
10103   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10104   const double *coo=m2->getCoords()->getConstPointer();
10105   const double *cooBis=m1->getCoords()->getConstPointer();
10106   int offset2=offset1+m2->getNumberOfNodes();
10107   intersectEdge.resize(ncell);
10108   for(int i=0;i<ncell;i++,cI++)
10109     {
10110       const std::vector<int>& divs=subDiv[i];
10111       int nnode=cI[1]-cI[0]-1;
10112       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10113       std::map<INTERP_KERNEL::Node *, int> mapp22;
10114       for(int j=0;j<nnode;j++)
10115         {
10116           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10117           int nnid=c[(*cI)+j+1];
10118           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10119           mapp22[nn]=nnid+offset1;
10120         }
10121       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10122       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10123         ((*it).second.first)->decrRef();
10124       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10125       std::map<INTERP_KERNEL::Node *,int> mapp3;
10126       for(std::size_t j=0;j<divs.size();j++)
10127         {
10128           int id=divs[j];
10129           INTERP_KERNEL::Node *tmp=0;
10130           if(id<offset1)
10131             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10132           else if(id<offset2)
10133             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10134           else
10135             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10136           addNodes[j]=tmp;
10137           mapp3[tmp]=id;
10138         }
10139       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10140       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10141         (*it)->decrRef();
10142       e->decrRef();
10143     }
10144 }
10145
10146 /*!
10147  * 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).
10148  * 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
10149  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10150  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10151  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10152  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10153  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10154  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10155  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10156  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10157  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10158  * \param [out] cut3DSuf input/output param.
10159  */
10160 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10161                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10162                                                    const int *desc, const int *descIndx, 
10163                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10164 {
10165   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10166   int nbOf3DSurfCell=(int)cut3DSurf.size();
10167   for(int i=0;i<nbOf3DSurfCell;i++)
10168     {
10169       std::vector<int> res;
10170       int offset=descIndx[i];
10171       int nbOfSeg=descIndx[i+1]-offset;
10172       for(int j=0;j<nbOfSeg;j++)
10173         {
10174           int edgeId=desc[offset+j];
10175           int status=cut3DCurve[edgeId];
10176           if(status!=-2)
10177             {
10178               if(status>-1)
10179                 res.push_back(status);
10180               else
10181                 {
10182                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10183                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10184                 }
10185             }
10186         }
10187       switch(res.size())
10188       {
10189         case 2:
10190           {
10191             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10192             break;
10193           }
10194         case 1:
10195         case 0:
10196           {
10197             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10198             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10199             if(res.size()==2)
10200               {
10201                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10202               }
10203             else
10204               {
10205                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10206               }
10207             break;
10208           }
10209         default:
10210           {// case when plane is on a multi colinear edge of a polyhedron
10211             if((int)res.size()==2*nbOfSeg)
10212               {
10213                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10214               }
10215             else
10216               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10217           }
10218       }
10219     }
10220 }
10221
10222 /*!
10223  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10224  * 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).
10225  * 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
10226  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10227  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10228  * \param desc is the descending connectivity 3D->3DSurf
10229  * \param descIndx is the descending connectivity index 3D->3DSurf
10230  */
10231 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10232                                                   const int *desc, const int *descIndx,
10233                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10234 {
10235   checkFullyDefined();
10236   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10237     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10238   const int *nodal3D=_nodal_connec->getConstPointer();
10239   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10240   int nbOfCells=getNumberOfCells();
10241   for(int i=0;i<nbOfCells;i++)
10242     {
10243       std::map<int, std::set<int> > m;
10244       int offset=descIndx[i];
10245       int nbOfFaces=descIndx[i+1]-offset;
10246       int start=-1;
10247       int end=-1;
10248       for(int j=0;j<nbOfFaces;j++)
10249         {
10250           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10251           if(p.first!=-1 && p.second!=-1)
10252             {
10253               if(p.first!=-2)
10254                 {
10255                   start=p.first; end=p.second;
10256                   m[p.first].insert(p.second);
10257                   m[p.second].insert(p.first);
10258                 }
10259               else
10260                 {
10261                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10262                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10263                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10264                   INTERP_KERNEL::NormalizedCellType cmsId;
10265                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10266                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10267                   for(unsigned k=0;k<nbOfNodesSon;k++)
10268                     {
10269                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10270                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10271                     }
10272                 }
10273             }
10274         }
10275       if(m.empty())
10276         continue;
10277       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10278       int prev=end;
10279       while(end!=start)
10280         {
10281           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10282           const std::set<int>& s=(*it).second;
10283           std::set<int> s2; s2.insert(prev);
10284           std::set<int> s3;
10285           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10286           if(s3.size()==1)
10287             {
10288               int val=*s3.begin();
10289               conn.push_back(start);
10290               prev=start;
10291               start=val;
10292             }
10293           else
10294             start=end;
10295         }
10296       conn.push_back(end);
10297       if(conn.size()>3)
10298         {
10299           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10300           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10301           cellIds->pushBackSilent(i);
10302         }
10303     }
10304 }
10305
10306 /*!
10307  * 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
10308  * 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
10309  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10310  * 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
10311  * 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.
10312  * 
10313  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10314  */
10315 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10316 {
10317   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10318   if(sz>=4)
10319     {
10320       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10321       if(cm.getDimension()==2)
10322         {
10323           const int *node=nodalConnBg+1;
10324           int startNode=*node++;
10325           double refX=coords[2*startNode];
10326           for(;node!=nodalConnEnd;node++)
10327             {
10328               if(coords[2*(*node)]<refX)
10329                 {
10330                   startNode=*node;
10331                   refX=coords[2*startNode];
10332                 }
10333             }
10334           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10335           refX=1e300;
10336           double tmp1;
10337           double tmp2[2];
10338           double angle0=-M_PI/2;
10339           //
10340           int nextNode=-1;
10341           int prevNode=-1;
10342           double resRef;
10343           double angleNext=0.;
10344           while(nextNode!=startNode)
10345             {
10346               nextNode=-1;
10347               resRef=1e300;
10348               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10349                 {
10350                   if(*node!=tmpOut.back() && *node!=prevNode)
10351                     {
10352                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10353                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10354                       double res;
10355                       if(angleM<=angle0)
10356                         res=angle0-angleM;
10357                       else
10358                         res=angle0-angleM+2.*M_PI;
10359                       if(res<resRef)
10360                         {
10361                           nextNode=*node;
10362                           resRef=res;
10363                           angleNext=angleM;
10364                         }
10365                     }
10366                 }
10367               if(nextNode!=startNode)
10368                 {
10369                   angle0=angleNext-M_PI;
10370                   if(angle0<-M_PI)
10371                     angle0+=2*M_PI;
10372                   prevNode=tmpOut.back();
10373                   tmpOut.push_back(nextNode);
10374                 }
10375             }
10376           std::vector<int> tmp3(2*(sz-1));
10377           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10378           std::copy(nodalConnBg+1,nodalConnEnd,it);
10379           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10380             {
10381               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10382               return false;
10383             }
10384           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10385             {
10386               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10387               return false;
10388             }
10389           else
10390             {
10391               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10392               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10393               return true;
10394             }
10395         }
10396       else
10397         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10398     }
10399   else
10400     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10401 }
10402
10403 /*!
10404  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10405  * 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.
10406  * 
10407  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10408  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10409  * \param [in,out] arr array in which the remove operation will be done.
10410  * \param [in,out] arrIndx array in the remove operation will modify
10411  * \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])
10412  * \return true if \b arr and \b arrIndx have been modified, false if not.
10413  */
10414 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10415 {
10416   if(!arrIndx || !arr)
10417     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10418   if(offsetForRemoval<0)
10419     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10420   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10421   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10422   int *arrIPtr=arrIndx->getPointer();
10423   *arrIPtr++=0;
10424   int previousArrI=0;
10425   const int *arrPtr=arr->getConstPointer();
10426   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10427   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10428     {
10429       if(*arrIPtr-previousArrI>offsetForRemoval)
10430         {
10431           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10432             {
10433               if(s.find(*work)==s.end())
10434                 arrOut.push_back(*work);
10435             }
10436         }
10437       previousArrI=*arrIPtr;
10438       *arrIPtr=(int)arrOut.size();
10439     }
10440   if(arr->getNumberOfTuples()==(int)arrOut.size())
10441     return false;
10442   arr->alloc((int)arrOut.size(),1);
10443   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10444   return true;
10445 }
10446
10447 /*!
10448  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10449  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10450  * The selection of extraction is done standardly in new2old format.
10451  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10452  *
10453  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10454  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10455  * \param [in] arrIn arr origin array from which the extraction will be done.
10456  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10457  * \param [out] arrOut the resulting array
10458  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10459  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10460  */
10461 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10462                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10463 {
10464   if(!arrIn || !arrIndxIn)
10465     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10466   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10467   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10469   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10470   const int *arrInPtr=arrIn->getConstPointer();
10471   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10472   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10473   if(nbOfGrps<0)
10474     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10475   int maxSizeOfArr=arrIn->getNumberOfTuples();
10476   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10477   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10478   arrIo->alloc((int)(sz+1),1);
10479   const int *idsIt=idsOfSelectBg;
10480   int *work=arrIo->getPointer();
10481   *work++=0;
10482   int lgth=0;
10483   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10484     {
10485       if(*idsIt>=0 && *idsIt<nbOfGrps)
10486         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10487       else
10488         {
10489           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10490           throw INTERP_KERNEL::Exception(oss.str().c_str());
10491         }
10492       if(lgth>=work[-1])
10493         *work=lgth;
10494       else
10495         {
10496           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10497           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10498           throw INTERP_KERNEL::Exception(oss.str().c_str());
10499         }
10500     }
10501   arro->alloc(lgth,1);
10502   work=arro->getPointer();
10503   idsIt=idsOfSelectBg;
10504   for(std::size_t i=0;i<sz;i++,idsIt++)
10505     {
10506       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10507         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10508       else
10509         {
10510           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10511           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10512           throw INTERP_KERNEL::Exception(oss.str().c_str());
10513         }
10514     }
10515   arrOut=arro.retn();
10516   arrIndexOut=arrIo.retn();
10517 }
10518
10519 /*!
10520  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10521  * 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 ).
10522  * The selection of extraction is done standardly in new2old format.
10523  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10524  *
10525  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10526  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10527  * \param [in] arrIn arr origin array from which the extraction will be done.
10528  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10529  * \param [out] arrOut the resulting array
10530  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10531  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10532  */
10533 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10534                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10535 {
10536   if(!arrIn || !arrIndxIn)
10537     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10538   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10539   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10540     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10541   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10542   const int *arrInPtr=arrIn->getConstPointer();
10543   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10544   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10545   if(nbOfGrps<0)
10546     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10547   int maxSizeOfArr=arrIn->getNumberOfTuples();
10548   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10549   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10550   arrIo->alloc((int)(sz+1),1);
10551   int idsIt=idsOfSelectStart;
10552   int *work=arrIo->getPointer();
10553   *work++=0;
10554   int lgth=0;
10555   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10556     {
10557       if(idsIt>=0 && idsIt<nbOfGrps)
10558         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10559       else
10560         {
10561           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10562           throw INTERP_KERNEL::Exception(oss.str().c_str());
10563         }
10564       if(lgth>=work[-1])
10565         *work=lgth;
10566       else
10567         {
10568           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10569           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10570           throw INTERP_KERNEL::Exception(oss.str().c_str());
10571         }
10572     }
10573   arro->alloc(lgth,1);
10574   work=arro->getPointer();
10575   idsIt=idsOfSelectStart;
10576   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10577     {
10578       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10579         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10580       else
10581         {
10582           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10583           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10584           throw INTERP_KERNEL::Exception(oss.str().c_str());
10585         }
10586     }
10587   arrOut=arro.retn();
10588   arrIndexOut=arrIo.retn();
10589 }
10590
10591 /*!
10592  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10593  * 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
10594  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10595  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10596  *
10597  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10598  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10599  * \param [in] arrIn arr origin array from which the extraction will be done.
10600  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10601  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10602  * \param [in] srcArrIndex index array of \b srcArr
10603  * \param [out] arrOut the resulting array
10604  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10605  * 
10606  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10607  */
10608 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10609                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10610                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10611 {
10612   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10613     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10614   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10615   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10616   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10617   std::vector<bool> v(nbOfTuples,true);
10618   int offset=0;
10619   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10620   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10621   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10622     {
10623       if(*it>=0 && *it<nbOfTuples)
10624         {
10625           v[*it]=false;
10626           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10627         }
10628       else
10629         {
10630           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10631           throw INTERP_KERNEL::Exception(oss.str().c_str());
10632         }
10633     }
10634   srcArrIndexPtr=srcArrIndex->getConstPointer();
10635   arrIo->alloc(nbOfTuples+1,1);
10636   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10637   const int *arrInPtr=arrIn->getConstPointer();
10638   const int *srcArrPtr=srcArr->getConstPointer();
10639   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10640   int *arroPtr=arro->getPointer();
10641   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10642     {
10643       if(v[ii])
10644         {
10645           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10646           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10647         }
10648       else
10649         {
10650           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10651           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10652           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10653         }
10654     }
10655   arrOut=arro.retn();
10656   arrIndexOut=arrIo.retn();
10657 }
10658
10659 /*!
10660  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10661  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10662  *
10663  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10664  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10665  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10666  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10667  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10668  * \param [in] srcArrIndex index array of \b srcArr
10669  * 
10670  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10671  */
10672 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10673                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10674 {
10675   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10676     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10677   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10678   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10679   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10680   int *arrInOutPtr=arrInOut->getPointer();
10681   const int *srcArrPtr=srcArr->getConstPointer();
10682   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10683     {
10684       if(*it>=0 && *it<nbOfTuples)
10685         {
10686           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10687             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10688           else
10689             {
10690               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] !";
10691               throw INTERP_KERNEL::Exception(oss.str().c_str());
10692             }
10693         }
10694       else
10695         {
10696           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10697           throw INTERP_KERNEL::Exception(oss.str().c_str());
10698         }
10699     }
10700 }
10701
10702 /*!
10703  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10704  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10705  * 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]].
10706  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10707  * A negative value in \b arrIn means that it is ignored.
10708  * 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.
10709  * 
10710  * \param [in] arrIn arr origin array from which the extraction will be done.
10711  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10712  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10713  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10714  */
10715 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10716 {
10717   int seed=0,nbOfDepthPeelingPerformed=0;
10718   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10719 }
10720
10721 /*!
10722  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10723  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10724  * 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]].
10725  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10726  * A negative value in \b arrIn means that it is ignored.
10727  * 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.
10728  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10729  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10730  * \param [in] arrIn arr origin array from which the extraction will be done.
10731  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10732  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10733  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10734  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10735  * \sa MEDCouplingUMesh::partitionBySpreadZone
10736  */
10737 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10738 {
10739   nbOfDepthPeelingPerformed=0;
10740   if(!arrIndxIn)
10741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10742   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10743   if(nbOfTuples<=0)
10744     {
10745       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10746       return ret;
10747     }
10748   //
10749   std::vector<bool> fetched(nbOfTuples,false);
10750   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10751 }
10752
10753 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10754 {
10755   nbOfDepthPeelingPerformed=0;
10756   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10757     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10758   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10759   std::vector<bool> fetched2(nbOfTuples,false);
10760   int i=0;
10761   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10762     {
10763       if(*seedElt>=0 && *seedElt<nbOfTuples)
10764         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10765       else
10766         { 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()); }
10767     }
10768   const int *arrInPtr=arrIn->getConstPointer();
10769   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10770   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
10771   std::vector<int> idsToFetch1(seedBg,seedEnd);
10772   std::vector<int> idsToFetch2;
10773   std::vector<int> *idsToFetch=&idsToFetch1;
10774   std::vector<int> *idsToFetchOther=&idsToFetch2;
10775   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
10776     {
10777       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
10778         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
10779           if(!fetched[*it2])
10780             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10781       std::swap(idsToFetch,idsToFetchOther);
10782       idsToFetchOther->clear();
10783       nbOfDepthPeelingPerformed++;
10784     }
10785   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10786   i=0;
10787   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10788   int *retPtr=ret->getPointer();
10789   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
10790     if(*it)
10791       *retPtr++=i;
10792   return ret.retn();
10793 }
10794
10795 /*!
10796  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10797  * 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
10798  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10799  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10800  *
10801  * \param [in] start begin of set of ids of the input extraction (included)
10802  * \param [in] end end of set of ids of the input extraction (excluded)
10803  * \param [in] step step of the set of ids in range mode.
10804  * \param [in] arrIn arr origin array from which the extraction will be done.
10805  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10806  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10807  * \param [in] srcArrIndex index array of \b srcArr
10808  * \param [out] arrOut the resulting array
10809  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10810  * 
10811  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
10812  */
10813 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10814                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10815                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10816 {
10817   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10818     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
10819   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10821   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10822   int offset=0;
10823   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10824   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10825   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
10826   int it=start;
10827   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10828     {
10829       if(it>=0 && it<nbOfTuples)
10830         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
10831       else
10832         {
10833           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10834           throw INTERP_KERNEL::Exception(oss.str().c_str());
10835         }
10836     }
10837   srcArrIndexPtr=srcArrIndex->getConstPointer();
10838   arrIo->alloc(nbOfTuples+1,1);
10839   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10840   const int *arrInPtr=arrIn->getConstPointer();
10841   const int *srcArrPtr=srcArr->getConstPointer();
10842   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10843   int *arroPtr=arro->getPointer();
10844   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10845     {
10846       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
10847       if(pos<0)
10848         {
10849           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10850           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10851         }
10852       else
10853         {
10854           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10855           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10856         }
10857     }
10858   arrOut=arro.retn();
10859   arrIndexOut=arrIo.retn();
10860 }
10861
10862 /*!
10863  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10864  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10865  *
10866  * \param [in] start begin of set of ids of the input extraction (included)
10867  * \param [in] end end of set of ids of the input extraction (excluded)
10868  * \param [in] step step of the set of ids in range mode.
10869  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10870  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10871  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10872  * \param [in] srcArrIndex index array of \b srcArr
10873  * 
10874  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10875  */
10876 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10877                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10878 {
10879   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10880     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
10881   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10882   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10883   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10884   int *arrInOutPtr=arrInOut->getPointer();
10885   const int *srcArrPtr=srcArr->getConstPointer();
10886   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
10887   int it=start;
10888   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10889     {
10890       if(it>=0 && it<nbOfTuples)
10891         {
10892           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
10893             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
10894           else
10895             {
10896               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
10897               throw INTERP_KERNEL::Exception(oss.str().c_str());
10898             }
10899         }
10900       else
10901         {
10902           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10903           throw INTERP_KERNEL::Exception(oss.str().c_str());
10904         }
10905     }
10906 }
10907
10908 /*!
10909  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
10910  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
10911  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
10912  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
10913  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
10914  * 
10915  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
10916  */
10917 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
10918 {
10919   checkFullyDefined();
10920   int mdim=getMeshDimension();
10921   int spaceDim=getSpaceDimension();
10922   if(mdim!=spaceDim)
10923     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
10924   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
10925   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
10926   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
10927   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
10928   ret->setCoords(getCoords());
10929   ret->allocateCells((int)partition.size());
10930   //
10931   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
10932     {
10933       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
10934       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
10935       switch(mdim)
10936       {
10937         case 2:
10938           cell=tmp->buildUnionOf2DMesh();
10939           break;
10940         case 3:
10941           cell=tmp->buildUnionOf3DMesh();
10942           break;
10943         default:
10944           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
10945       }
10946
10947       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
10948     }
10949   //
10950   ret->finishInsertingCells();
10951   return ret.retn();
10952 }
10953
10954 /*!
10955  * This method partitions \b this into contiguous zone.
10956  * This method only needs a well defined connectivity. Coordinates are not considered here.
10957  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
10958  */
10959 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
10960 {
10961   int nbOfCellsCur=getNumberOfCells();
10962   std::vector<DataArrayInt *> ret;
10963   if(nbOfCellsCur<=0)
10964     return ret;
10965   DataArrayInt *neigh=0,*neighI=0;
10966   computeNeighborsOfCells(neigh,neighI);
10967   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10968   std::vector<bool> fetchedCells(nbOfCellsCur,false);
10969   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10970   int seed=0;
10971   while(seed<nbOfCellsCur)
10972     {
10973       int nbOfPeelPerformed=0;
10974       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10975       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10976     }
10977   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10978     ret.push_back((*it).retn());
10979   return ret;
10980 }
10981
10982 /*!
10983  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10984  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10985  *
10986  * \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.
10987  * \return a newly allocated DataArrayInt to be managed by the caller.
10988  * \throw In case of \a code has not the right format (typically of size 3*n)
10989  */
10990 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10991 {
10992   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10993   std::size_t nb=code.size()/3;
10994   if(code.size()%3!=0)
10995     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10996   ret->alloc((int)nb,2);
10997   int *retPtr=ret->getPointer();
10998   for(std::size_t i=0;i<nb;i++,retPtr+=2)
10999     {
11000       retPtr[0]=code[3*i+2];
11001       retPtr[1]=code[3*i+2]+code[3*i+1];
11002     }
11003   return ret.retn();
11004 }
11005
11006 /*!
11007  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11008  * All cells in \a this are expected to be linear 3D cells.
11009  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11010  * It leads to an increase to number of cells.
11011  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11012  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11013  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11014  *
11015  * \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.
11016  *                      For all other cells, the splitting policy will be ignored.
11017  * \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. 
11018  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11019  *          an id of old cell producing it. The caller is to delete this array using
11020  *         decrRef() as it is no more needed.
11021  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11022  *
11023  * \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
11024  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11025  * 
11026  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11027  * \throw If \a this is not fully constituted with linear 3D cells.
11028  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11029  */
11030 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11031 {
11032   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11033   checkConnectivityFullyDefined();
11034   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11035     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11036   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11037   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11038   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11039   int *retPt(ret->getPointer());
11040   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11041   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11042   const int *oldc(_nodal_connec->begin());
11043   const int *oldci(_nodal_connec_index->begin());
11044   const double *coords(_coords->begin());
11045   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11046     {
11047       std::vector<int> a; std::vector<double> b;
11048       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11049       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11050       const int *aa(&a[0]);
11051       if(!b.empty())
11052         {
11053           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11054             if(*it<0)
11055               *it=(-(*(it))-1+nbNodes);
11056           addPts->insertAtTheEnd(b.begin(),b.end());
11057           nbNodes+=(int)b.size()/3;
11058         }
11059       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11060         newConn->insertAtTheEnd(aa,aa+4);
11061     }
11062   if(!addPts->empty())
11063     {
11064       addPts->rearrange(3);
11065       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11066       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11067       ret0->setCoords(addPts);
11068     }
11069   else
11070     {
11071       nbOfAdditionalPoints=0;
11072       ret0->setCoords(getCoords());
11073     }
11074   ret0->setNodalConnectivity(newConn);
11075   //
11076   ret->computeOffsets2();
11077   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11078   return ret0.retn();
11079 }
11080
11081 /*!
11082  * 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). 
11083  *
11084  * \sa MEDCouplingUMesh::split2DCells
11085  */
11086 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11087 {
11088   checkConnectivityFullyDefined();
11089   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11090   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11091   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11092   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11093   int prevPosOfCi(ciPtr[0]);
11094   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11095     {
11096       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11097       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11098       for(int j=0;j<sz;j++)
11099         {
11100           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11101           for(int k=0;k<sz2;k++)
11102             *cPtr++=subPtr[offset2+k];
11103           if(j!=sz-1)
11104             *cPtr++=oldConn[prevPosOfCi+j+2];
11105           deltaSz+=sz2;
11106         }
11107       prevPosOfCi=ciPtr[1];
11108       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11109     }
11110   if(c->end()!=cPtr)
11111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11112   _nodal_connec->decrRef();
11113   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11114 }
11115
11116 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11117 {
11118   if(id!=-1)
11119     return id;
11120   else
11121     {
11122       int ret(nodesCnter++);
11123       double newPt[2];
11124       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11125       addCoo.insertAtTheEnd(newPt,newPt+2);
11126       return ret;
11127     }
11128 }
11129
11130 /// @cond INTERNAL
11131
11132 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)
11133 {
11134   int tmp[3];
11135   int trueStart(start>=0?start:nbOfEdges+start);
11136   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11137   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11138   if(linOrArc)
11139     {
11140       if(stp-start>1)
11141         {
11142           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11143           InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11144           middles.push_back(tmp3+offset);
11145         }
11146       else
11147         middles.push_back(connBg[trueStart+nbOfEdges]);
11148     }
11149 }
11150
11151 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)
11152 {
11153   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11154   newConnOfCell->pushBackSilent(tmpEnd);
11155   if(linOrArc)
11156     {
11157       if(stp-start>1)
11158         {
11159           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11160           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11161           middles.push_back(tmp3+offset);
11162         }
11163       else
11164         middles.push_back(connBg[start+nbOfEdges]);
11165     }
11166 }
11167
11168 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)
11169 {
11170   if(linOrArc)
11171     {
11172       if(stp-start>1)
11173         {
11174           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11175           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11176           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11177           middles.push_back(tmp3+offset);
11178         }
11179       else
11180         middles.push_back(connBg[start+nbOfEdges]);
11181     }
11182 }
11183
11184 /// @cond INTERNAL
11185
11186 /*!
11187  * 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 ) .
11188  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11189  */
11190 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11191 {
11192   std::size_t sz(std::distance(connBg,connEnd));
11193   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11194     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11195   sz--;
11196   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11197   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11198   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
11199   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11200   INTERP_KERNEL::NormalizedCellType typeOfSon;
11201   std::vector<int> middles;
11202   bool ret(false);
11203   for(;nbOfHit<nbs;nbOfTurn++)
11204     {
11205       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11206       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11207       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11208       posEndElt++;
11209       nbOfHit++;
11210       unsigned endI(nbs-nbOfHit);
11211       for(unsigned i=0;i<endI;i++)
11212         {
11213           cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
11214           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11215           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11216           bool isColinear(eint->areColinears());
11217           if(isColinear)
11218             {
11219               nbOfHit++;
11220               posEndElt++;
11221               ret=true;
11222             }
11223           delete eint;
11224           eCand->decrRef();
11225           if(!isColinear)
11226             {
11227               if(nbOfTurn==0)
11228                 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
11229                   unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
11230                   for(unsigned ii=0;ii<endII;ii++)
11231                     {
11232                       cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
11233                       eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
11234                       eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
11235                       isColinear=eint->areColinears();
11236                       if(isColinear)
11237                         {
11238                           nbOfHit++;
11239                           posBaseElt--;
11240                           ret=true;
11241                         }
11242                       delete eint;
11243                       eCand->decrRef();
11244                       if(!isColinear)
11245                         break;
11246                     }
11247                 }
11248               break;
11249             }
11250         }
11251       //push [posBaseElt,posEndElt) in newConnOfCell using e
11252       if(nbOfTurn==0)
11253         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11254       else if(nbOfHit!=nbs)
11255         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11256       else
11257         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11258       posBaseElt=posEndElt;
11259       e->decrRef();
11260     }
11261   if(!middles.empty())
11262     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11263   return ret;
11264 }
11265
11266 /*!
11267  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11268  *
11269  * \return  int - the number of new nodes created.
11270  * \sa MEDCouplingUMesh::split2DCells
11271  */
11272 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11273 {
11274   checkCoherency();
11275   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11277   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11278   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11279   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11280   const double *oldCoordsPtr(getCoords()->begin());
11281   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11282   int prevPosOfCi(ciPtr[0]);
11283   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11284     {
11285       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11286       for(int j=0;j<sz;j++)
11287         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11288       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11289       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11290         {
11291           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11292           if(sz2==0)
11293             {
11294               if(j<sz-1)
11295                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11296               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11297               continue;
11298             }
11299           std::vector<INTERP_KERNEL::Node *> ns(3);
11300           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11301           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11302           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11303           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11304           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11305             {
11306               cPtr[1]=subPtr[offset2+k];
11307               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11308             }
11309           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11310           if(j!=sz-1)
11311             { cPtr[1]=tmpEnd; }
11312           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11313         }
11314       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11315       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11316     }
11317   if(c->end()!=cPtr)
11318     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11319   _nodal_connec->decrRef();
11320   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11321   addCoo->rearrange(2);
11322   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11323   setCoords(coo);
11324   return addCoo->getNumberOfTuples();
11325 }
11326
11327 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11328     _own_cell(true),_cell_id(-1),_nb_cell(0)
11329 {
11330   if(mesh)
11331     {
11332       mesh->incrRef();
11333       _nb_cell=mesh->getNumberOfCells();
11334     }
11335 }
11336
11337 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11338 {
11339   if(_mesh)
11340     _mesh->decrRef();
11341   if(_own_cell)
11342     delete _cell;
11343 }
11344
11345 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11346     _own_cell(false),_cell_id(bg-1),
11347     _nb_cell(end)
11348 {
11349   if(mesh)
11350     mesh->incrRef();
11351 }
11352
11353 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11354 {
11355   _cell_id++;
11356   if(_cell_id<_nb_cell)
11357     {
11358       _cell->next();
11359       return _cell;
11360     }
11361   else
11362     return 0;
11363 }
11364
11365 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11366 {
11367   if(_mesh)
11368     _mesh->incrRef();
11369 }
11370
11371 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11372 {
11373   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11374 }
11375
11376 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11377 {
11378   if(_mesh)
11379     _mesh->decrRef();
11380 }
11381
11382 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11383     _itc(itc),
11384     _bg(bg),_end(end)
11385 {
11386   if(_mesh)
11387     _mesh->incrRef();
11388 }
11389
11390 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11391 {
11392   if(_mesh)
11393     _mesh->decrRef();
11394 }
11395
11396 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11397 {
11398   return _type;
11399 }
11400
11401 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11402 {
11403   return _end-_bg;
11404 }
11405
11406 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11407 {
11408   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11409 }
11410
11411 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11412 {
11413   if(mesh)
11414     {
11415       mesh->incrRef();
11416       _nb_cell=mesh->getNumberOfCells();
11417     }
11418 }
11419
11420 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11421 {
11422   if(_mesh)
11423     _mesh->decrRef();
11424   delete _cell;
11425 }
11426
11427 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11428 {
11429   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11430   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11431   if(_cell_id<_nb_cell)
11432     {
11433       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11434       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11435       int startId=_cell_id;
11436       _cell_id+=nbOfElems;
11437       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11438     }
11439   else
11440     return 0;
11441 }
11442
11443 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11444 {
11445   if(mesh)
11446     {
11447       _conn=mesh->getNodalConnectivity()->getPointer();
11448       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11449     }
11450 }
11451
11452 void MEDCouplingUMeshCell::next()
11453 {
11454   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11455     {
11456       _conn+=_conn_lgth;
11457       _conn_indx++;
11458     }
11459   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11460 }
11461
11462 std::string MEDCouplingUMeshCell::repr() const
11463 {
11464   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11465     {
11466       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11467       oss << " : ";
11468       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11469       return oss.str();
11470     }
11471   else
11472     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11473 }
11474
11475 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11476 {
11477   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11478     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11479   else
11480     return INTERP_KERNEL::NORM_ERROR;
11481 }
11482
11483 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11484 {
11485   lgth=_conn_lgth;
11486   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11487     return _conn;
11488   else
11489     return 0;
11490 }