Salome HOME
f213a9d42d53de8b084d6e3fb19c1913bfbc112e
[modules/med.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 /*!
93  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94  * The coordinates are shared between \a this and the returned instance.
95  * 
96  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97  * \sa MEDCouplingUMesh::deepCpy
98  */
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
100 {
101   checkConnectivityFullyDefined();
102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104   ret->setConnectivity(c,ci);
105   return ret.retn();
106 }
107
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
109 {
110   if(!other)
111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
113   if(!otherC)
114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
117 }
118
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
120 {
121   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
122   return ret;
123 }
124
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
126 {
127   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
128   ret.push_back(_nodal_connec);
129   ret.push_back(_nodal_connec_index);
130   return ret;
131 }
132
133 void MEDCouplingUMesh::updateTime() const
134 {
135   MEDCouplingPointSet::updateTime();
136   if(_nodal_connec)
137     {
138       updateTimeWith(*_nodal_connec);
139     }
140   if(_nodal_connec_index)
141     {
142       updateTimeWith(*_nodal_connec_index);
143     }
144 }
145
146 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
147 {
148 }
149
150 /*!
151  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
152  * then \a this mesh is most probably is writable, exchangeable and available for most
153  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
154  * this method to check that all is in order with \a this mesh.
155  *  \throw If the mesh dimension is not set.
156  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
157  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
158  *  \throw If the connectivity data array has more than one component.
159  *  \throw If the connectivity data array has a named component.
160  *  \throw If the connectivity index data array has more than one component.
161  *  \throw If the connectivity index data array has a named component.
162  */
163 void MEDCouplingUMesh::checkCoherency() const
164 {
165   if(_mesh_dim<-1)
166     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
167   if(_mesh_dim!=-1)
168     MEDCouplingPointSet::checkCoherency();
169   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
170     {
171       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
172         {
173           std::ostringstream message;
174           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
175           throw INTERP_KERNEL::Exception(message.str().c_str());
176         }
177     }
178   if(_nodal_connec)
179     {
180       if(_nodal_connec->getNumberOfComponents()!=1)
181         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
182       if(_nodal_connec->getInfoOnComponent(0)!="")
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
184     }
185   else
186     if(_mesh_dim!=-1)
187       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
188   if(_nodal_connec_index)
189     {
190       if(_nodal_connec_index->getNumberOfComponents()!=1)
191         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
192       if(_nodal_connec_index->getInfoOnComponent(0)!="")
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
194     }
195   else
196     if(_mesh_dim!=-1)
197       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
198 }
199
200 /*!
201  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
202  * then \a this mesh is most probably is writable, exchangeable and available for all
203  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
204  * method thoroughly checks the nodal connectivity.
205  *  \param [in] eps - a not used parameter.
206  *  \throw If the mesh dimension is not set.
207  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
208  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
209  *  \throw If the connectivity data array has more than one component.
210  *  \throw If the connectivity data array has a named component.
211  *  \throw If the connectivity index data array has more than one component.
212  *  \throw If the connectivity index data array has a named component.
213  *  \throw If number of nodes defining an element does not correspond to the type of element.
214  *  \throw If the nodal connectivity includes an invalid node id.
215  */
216 void MEDCouplingUMesh::checkCoherency1(double eps) const
217 {
218   checkCoherency();
219   if(_mesh_dim==-1)
220     return ;
221   int meshDim=getMeshDimension();
222   int nbOfNodes=getNumberOfNodes();
223   int nbOfCells=getNumberOfCells();
224   const int *ptr=_nodal_connec->getConstPointer();
225   const int *ptrI=_nodal_connec_index->getConstPointer();
226   for(int i=0;i<nbOfCells;i++)
227     {
228       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
229       if((int)cm.getDimension()!=meshDim)
230         {
231           std::ostringstream oss;
232           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
233           throw INTERP_KERNEL::Exception(oss.str().c_str());
234         }
235       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
236       if(!cm.isDynamic())
237         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
238           {
239             std::ostringstream oss;
240             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
241             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
242             throw INTERP_KERNEL::Exception(oss.str().c_str());
243           }
244       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
245         {
246           int nodeId=*w;
247           if(nodeId>=0)
248             {
249               if(nodeId>=nbOfNodes)
250                 {
251                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
252                   throw INTERP_KERNEL::Exception(oss.str().c_str());
253                 }
254             }
255           else if(nodeId<-1)
256             {
257               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
258               throw INTERP_KERNEL::Exception(oss.str().c_str());
259             }
260           else
261             {
262               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
263                 {
264                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
265                   throw INTERP_KERNEL::Exception(oss.str().c_str());
266                 }
267             }
268         }
269     }
270 }
271
272
273 /*!
274  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
275  * then \a this mesh is most probably is writable, exchangeable and available for all
276  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
277  *  \param [in] eps - a not used parameter.
278  *  \throw If the mesh dimension is not set.
279  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
280  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
281  *  \throw If the connectivity data array has more than one component.
282  *  \throw If the connectivity data array has a named component.
283  *  \throw If the connectivity index data array has more than one component.
284  *  \throw If the connectivity index data array has a named component.
285  *  \throw If number of nodes defining an element does not correspond to the type of element.
286  *  \throw If the nodal connectivity includes an invalid node id.
287  */
288 void MEDCouplingUMesh::checkCoherency2(double eps) const
289 {
290   checkCoherency1(eps);
291 }
292
293 /*!
294  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
295  * elements contained in the mesh. For more info on the mesh dimension see
296  * \ref MEDCouplingUMeshPage.
297  *  \param [in] meshDim - a new mesh dimension.
298  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
299  */
300 void MEDCouplingUMesh::setMeshDimension(int meshDim)
301 {
302   if(meshDim<-1 || meshDim>3)
303     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
304   _mesh_dim=meshDim;
305   declareAsNew();
306 }
307
308 /*!
309  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
310  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
311  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
312  *
313  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
314  *
315  *  \if ENABLE_EXAMPLES
316  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
317  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
318  *  \endif
319  */
320 void MEDCouplingUMesh::allocateCells(int nbOfCells)
321 {
322   if(nbOfCells<0)
323     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
324   if(_nodal_connec_index)
325     {
326       _nodal_connec_index->decrRef();
327     }
328   if(_nodal_connec)
329     {
330       _nodal_connec->decrRef();
331     }
332   _nodal_connec_index=DataArrayInt::New();
333   _nodal_connec_index->reserve(nbOfCells+1);
334   _nodal_connec_index->pushBackSilent(0);
335   _nodal_connec=DataArrayInt::New();
336   _nodal_connec->reserve(2*nbOfCells);
337   _types.clear();
338   declareAsNew();
339 }
340
341 /*!
342  * Appends a cell to the connectivity array. For deeper understanding what is
343  * happening see \ref MEDCouplingUMeshNodalConnectivity.
344  *  \param [in] type - type of cell to add.
345  *  \param [in] size - number of nodes constituting this cell.
346  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
347  * 
348  *  \if ENABLE_EXAMPLES
349  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
350  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
351  *  \endif
352  */
353 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
354 {
355   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
356   if(_nodal_connec_index==0)
357     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
358   if((int)cm.getDimension()==_mesh_dim)
359     {
360       if(!cm.isDynamic())
361         if(size!=(int)cm.getNumberOfNodes())
362           {
363             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
364             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
365             throw INTERP_KERNEL::Exception(oss.str().c_str());
366           }
367       int idx=_nodal_connec_index->back();
368       int val=idx+size+1;
369       _nodal_connec_index->pushBackSilent(val);
370       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
371       _types.insert(type);
372     }
373   else
374     {
375       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
376       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
377       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
378       throw INTERP_KERNEL::Exception(oss.str().c_str());
379     }
380 }
381
382 /*!
383  * Compacts data arrays to release unused memory. This method is to be called after
384  * finishing cell insertion using \a this->insertNextCell().
385  * 
386  *  \if ENABLE_EXAMPLES
387  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
388  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
389  *  \endif
390  */
391 void MEDCouplingUMesh::finishInsertingCells()
392 {
393   _nodal_connec->pack();
394   _nodal_connec_index->pack();
395   _nodal_connec->declareAsNew();
396   _nodal_connec_index->declareAsNew();
397   updateTime();
398 }
399
400 /*!
401  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
402  * Useful for python users.
403  */
404 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
405 {
406   return new MEDCouplingUMeshCellIterator(this);
407 }
408
409 /*!
410  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
411  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
412  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
413  * Useful for python users.
414  */
415 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
416 {
417   if(!checkConsecutiveCellTypes())
418     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
419   return new MEDCouplingUMeshCellByTypeEntry(this);
420 }
421
422 /*!
423  * Returns a set of all cell types available in \a this mesh.
424  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
425  * \warning this method does not throw any exception even if \a this is not defined.
426  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
427  */
428 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
429 {
430   return _types;
431 }
432
433 /*!
434  * This method returns the sorted list of geometric types in \a this.
435  * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
436  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
437  *
438  * \throw if connectivity in \a this is not correctly defined.
439  *  
440  * \sa MEDCouplingMesh::getAllGeoTypes
441  */
442 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
443 {
444   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
445   checkConnectivityFullyDefined();
446   int nbOfCells(getNumberOfCells());
447   if(nbOfCells==0)
448     return ret;
449   if(getMeshLength()<1)
450     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
451   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
452   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
453   for(int i=1;i<nbOfCells;i++,ci++)
454     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
455       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
456   return ret;
457 }
458
459 /*!
460  * This method is a method that compares \a this and \a other.
461  * This method compares \b all attributes, even names and component names.
462  */
463 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
464 {
465   if(!other)
466     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
467   std::ostringstream oss; oss.precision(15);
468   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
469   if(!otherC)
470     {
471       reason="mesh given in input is not castable in MEDCouplingUMesh !";
472       return false;
473     }
474   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
475     return false;
476   if(_mesh_dim!=otherC->_mesh_dim)
477     {
478       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
479       reason=oss.str();
480       return false;
481     }
482   if(_types!=otherC->_types)
483     {
484       oss << "umesh geometric type mismatch :\nThis geometric types are :";
485       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
486         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
487       oss << "\nOther geometric types are :";
488       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
489         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
490       reason=oss.str();
491       return false;
492     }
493   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
494     if(_nodal_connec==0 || otherC->_nodal_connec==0)
495       {
496         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
497         return false;
498       }
499   if(_nodal_connec!=otherC->_nodal_connec)
500     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
501       {
502         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
503         return false;
504       }
505   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
506     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
507       {
508         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
509         return false;
510       }
511   if(_nodal_connec_index!=otherC->_nodal_connec_index)
512     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
513       {
514         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
515         return false;
516       }
517   return true;
518 }
519
520 /*!
521  * Checks if data arrays of this mesh (node coordinates, nodal
522  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
523  * not considered.
524  *  \param [in] other - the mesh to compare with.
525  *  \param [in] prec - precision value used to compare node coordinates.
526  *  \return bool - \a true if the two meshes are same.
527  */
528 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
529 {
530   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
531   if(!otherC)
532     return false;
533   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
534     return false;
535   if(_mesh_dim!=otherC->_mesh_dim)
536     return false;
537   if(_types!=otherC->_types)
538     return false;
539   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
540     if(_nodal_connec==0 || otherC->_nodal_connec==0)
541       return false;
542   if(_nodal_connec!=otherC->_nodal_connec)
543     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
544       return false;
545   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
546     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
547       return false;
548   if(_nodal_connec_index!=otherC->_nodal_connec_index)
549     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
550       return false;
551   return true;
552 }
553
554 /*!
555  * Checks if \a this and \a other meshes are geometrically equivalent with high
556  * probability, else an exception is thrown. The meshes are considered equivalent if
557  * (1) meshes contain the same number of nodes and the same number of elements of the
558  * same types (2) three cells of the two meshes (first, last and middle) are based
559  * on coincident nodes (with a specified precision).
560  *  \param [in] other - the mesh to compare with.
561  *  \param [in] prec - the precision used to compare nodes of the two meshes.
562  *  \throw If the two meshes do not match.
563  */
564 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
565 {
566   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
567   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
568   if(!otherC)
569     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
570 }
571
572 /*!
573  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
574  * cells each node belongs to.
575  * \warning For speed reasons, this method does not check if node ids in the nodal
576  *          connectivity correspond to the size of node coordinates array.
577  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
578  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
579  *        dividing cell ids in \a revNodal into groups each referring to one
580  *        node. Its every element (except the last one) is an index pointing to the
581  *         first id of a group of cells. For example cells sharing the node #1 are 
582  *        described by following range of indices: 
583  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
584  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
585  *        Number of cells sharing the *i*-th node is
586  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
587  * \throw If the coordinates array is not set.
588  * \throw If the nodal connectivity of cells is not defined.
589  * 
590  * \if ENABLE_EXAMPLES
591  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
592  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
593  * \endif
594  */
595 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
596 {
597   checkFullyDefined();
598   int nbOfNodes=getNumberOfNodes();
599   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
600   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
601   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
602   const int *conn=_nodal_connec->getConstPointer();
603   const int *connIndex=_nodal_connec_index->getConstPointer();
604   int nbOfCells=getNumberOfCells();
605   int nbOfEltsInRevNodal=0;
606   for(int eltId=0;eltId<nbOfCells;eltId++)
607     {
608       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
609       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
610       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
611         if(*iter>=0)//for polyhedrons
612           {
613             nbOfEltsInRevNodal++;
614             revNodalIndxPtr[(*iter)+1]++;
615           }
616     }
617   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
618   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
619   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
620   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
621   for(int eltId=0;eltId<nbOfCells;eltId++)
622     {
623       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
624       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
625       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
626         if(*iter>=0)//for polyhedrons
627           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
628     }
629 }
630
631 /// @cond INTERNAL
632
633 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
634 {
635   return id;
636 }
637
638 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
639 {
640   if(!compute)
641     return id+1;
642   else
643     {
644       if(cm.getOrientationStatus(nb,conn1,conn2))
645         return id+1;
646       else
647         return -(id+1);
648     }
649 }
650
651 class MinusOneSonsGenerator
652 {
653 public:
654   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
655   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
656   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
657   static const int DELTA=1;
658 private:
659   const INTERP_KERNEL::CellModel& _cm;
660 };
661
662 class MinusOneSonsGeneratorBiQuadratic
663 {
664 public:
665   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
666   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
667   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
668   static const int DELTA=1;
669 private:
670   const INTERP_KERNEL::CellModel& _cm;
671 };
672
673 class MinusTwoSonsGenerator
674 {
675 public:
676   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
677   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
678   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
679   static const int DELTA=2;
680 private:
681   const INTERP_KERNEL::CellModel& _cm;
682 };
683
684 /// @endcond
685
686 /*!
687  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
688  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
689  * describing correspondence between cells of \a this and the result meshes are
690  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
691  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
692  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
693  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
694  * \warning For speed reasons, this method does not check if node ids in the nodal
695  *          connectivity correspond to the size of node coordinates array.
696  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
697  *          to write this mesh to the MED file, its cells must be sorted using
698  *          sortCellsInMEDFileFrmt().
699  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
700  *         each cell of \a this mesh.
701  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
702  *        dividing cell ids in \a desc into groups each referring to one
703  *        cell of \a this mesh. Its every element (except the last one) is an index
704  *        pointing to the first id of a group of cells. For example cells of the
705  *        result mesh bounding the cell #1 of \a this mesh are described by following
706  *        range of indices:
707  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
708  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
709  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
710  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
711  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
712  *         by each cell of the result mesh.
713  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
714  *        in the result mesh,
715  *        dividing cell ids in \a revDesc into groups each referring to one
716  *        cell of the result mesh the same way as \a descIndx divides \a desc.
717  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
718  *        delete this mesh using decrRef() as it is no more needed.
719  *  \throw If the coordinates array is not set.
720  *  \throw If the nodal connectivity of cells is node defined.
721  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
722  *         revDescIndx == NULL.
723  * 
724  *  \if ENABLE_EXAMPLES
725  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
726  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
727  *  \endif
728  * \sa buildDescendingConnectivity2()
729  */
730 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
731 {
732   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
733 }
734
735 /*!
736  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
737  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
738  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
739  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
740  * \sa MEDCouplingUMesh::buildDescendingConnectivity
741  */
742 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
743 {
744   checkFullyDefined();
745   if(getMeshDimension()!=3)
746     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
747   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
748 }
749
750 /*!
751  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
752  * this->getMeshDimension(), that bound cells of \a this mesh. In
753  * addition arrays describing correspondence between cells of \a this and the result
754  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
755  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
756  *  mesh. This method differs from buildDescendingConnectivity() in that apart
757  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
758  * result meshes. So a positive id means that order of nodes in corresponding cells
759  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
760  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
761  * i.e. cell ids are one-based.
762  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
763  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
764  * \warning For speed reasons, this method does not check if node ids in the nodal
765  *          connectivity correspond to the size of node coordinates array.
766  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
767  *          to write this mesh to the MED file, its cells must be sorted using
768  *          sortCellsInMEDFileFrmt().
769  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
770  *         each cell of \a this mesh.
771  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
772  *        dividing cell ids in \a desc into groups each referring to one
773  *        cell of \a this mesh. Its every element (except the last one) is an index
774  *        pointing to the first id of a group of cells. For example cells of the
775  *        result mesh bounding the cell #1 of \a this mesh are described by following
776  *        range of indices:
777  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
778  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
779  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
780  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
781  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
782  *         by each cell of the result mesh.
783  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
784  *        in the result mesh,
785  *        dividing cell ids in \a revDesc into groups each referring to one
786  *        cell of the result mesh the same way as \a descIndx divides \a desc.
787  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
788  *        shares the node coordinates array with \a this mesh. The caller is to
789  *        delete this mesh using decrRef() as it is no more needed.
790  *  \throw If the coordinates array is not set.
791  *  \throw If the nodal connectivity of cells is node defined.
792  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
793  *         revDescIndx == NULL.
794  * 
795  *  \if ENABLE_EXAMPLES
796  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
797  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
798  *  \endif
799  * \sa buildDescendingConnectivity()
800  */
801 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
802 {
803   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
804 }
805
806 /*!
807  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
808  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
809  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
810  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
811  *
812  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
813  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
814  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
815  */
816 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
817 {
818   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
819   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
822   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
823   meshDM1=0;
824   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
825 }
826
827 /*!
828  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
829  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
830  * excluding a set of meshdim-1 cells in input descending connectivity.
831  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
832  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
833  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
834  *
835  * \param [in] desc descending connectivity array.
836  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
837  * \param [in] revDesc reverse descending connectivity array.
838  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
839  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
840  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
841  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
842  */
843 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
844                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
845 {
846   if(!desc || !descIndx || !revDesc || !revDescIndx)
847     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
848   const int *descPtr=desc->getConstPointer();
849   const int *descIPtr=descIndx->getConstPointer();
850   const int *revDescPtr=revDesc->getConstPointer();
851   const int *revDescIPtr=revDescIndx->getConstPointer();
852   //
853   int nbCells=descIndx->getNumberOfTuples()-1;
854   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
855   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
856   int *out1Ptr=out1->getPointer();
857   *out1Ptr++=0;
858   out0->reserve(desc->getNumberOfTuples());
859   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
860     {
861       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
862         {
863           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
864           s.erase(i);
865           out0->insertAtTheEnd(s.begin(),s.end());
866         }
867       *out1Ptr=out0->getNumberOfTuples();
868     }
869   neighbors=out0.retn();
870   neighborsIndx=out1.retn();
871 }
872
873 /*!
874  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
875  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
876  * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
877  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
878  *
879  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
880  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
881  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
882  */
883 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
884 {
885   checkFullyDefined();
886   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
888   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
889   switch(mdim)
890   {
891     case 3:
892       {
893         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
894         break;
895       }
896     case 2:
897       {
898         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
899         break;
900       }
901     case 1:
902       {
903         mesh1D=const_cast<MEDCouplingUMesh *>(this);
904         mesh1D->incrRef();
905         break;
906       }
907     default:
908       {
909         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
910       }
911   }
912   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
913   mesh1D->getReverseNodalConnectivity(desc,descIndx);
914   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
915   ret0->alloc(desc->getNumberOfTuples(),1);
916   int *r0Pt(ret0->getPointer());
917   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
918   for(int i=0;i<nbNodes;i++,rni++)
919     {
920       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
921         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
922     }
923   neighbors=ret0.retn();
924   neighborsIdx=descIndx.retn();
925 }
926
927 /// @cond INTERNAL
928
929 /*!
930  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
931  * For speed reasons no check of this will be done.
932  */
933 template<class SonsGenerator>
934 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
935 {
936   if(!desc || !descIndx || !revDesc || !revDescIndx)
937     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
938   checkConnectivityFullyDefined();
939   int nbOfCells=getNumberOfCells();
940   int nbOfNodes=getNumberOfNodes();
941   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
942   int *revNodalIndxPtr=revNodalIndx->getPointer();
943   const int *conn=_nodal_connec->getConstPointer();
944   const int *connIndex=_nodal_connec_index->getConstPointer();
945   std::string name="Mesh constituent of "; name+=getName();
946   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
947   ret->setCoords(getCoords());
948   ret->allocateCells(2*nbOfCells);
949   descIndx->alloc(nbOfCells+1,1);
950   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
951   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
952   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
953     {
954       int pos=connIndex[eltId];
955       int posP1=connIndex[eltId+1];
956       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
957       SonsGenerator sg(cm);
958       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
959       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
960       for(unsigned i=0;i<nbOfSons;i++)
961         {
962           INTERP_KERNEL::NormalizedCellType cmsId;
963           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
964           for(unsigned k=0;k<nbOfNodesSon;k++)
965             if(tmp[k]>=0)
966               revNodalIndxPtr[tmp[k]+1]++;
967           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
968           revDesc2->pushBackSilent(eltId);
969         }
970       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
971     }
972   int nbOfCellsM1=ret->getNumberOfCells();
973   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
975   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
976   int *revNodalPtr=revNodal->getPointer();
977   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
978   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
979   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
980     {
981       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
982       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
983       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
984         if(*iter>=0)//for polyhedrons
985           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
986     }
987   //
988   DataArrayInt *commonCells=0,*commonCellsI=0;
989   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
990   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
991   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
992   int newNbOfCellsM1=-1;
993   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
994                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
995   std::vector<bool> isImpacted(nbOfCellsM1,false);
996   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
997     for(int work2=work[0];work2!=work[1];work2++)
998       isImpacted[commonCellsPtr[work2]]=true;
999   const int *o2nM1Ptr=o2nM1->getConstPointer();
1000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1001   const int *n2oM1Ptr=n2oM1->getConstPointer();
1002   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1003   ret2->copyTinyInfoFrom(this);
1004   desc->alloc(descIndx->back(),1);
1005   int *descPtr=desc->getPointer();
1006   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1007   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1008     {
1009       if(!isImpacted[i])
1010         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1011       else
1012         {
1013           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1014             {
1015               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1016               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1017             }
1018           else
1019             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1020         }
1021     }
1022   revDesc->reserve(newNbOfCellsM1);
1023   revDescIndx->alloc(newNbOfCellsM1+1,1);
1024   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1025   const int *revDesc2Ptr=revDesc2->getConstPointer();
1026   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1027     {
1028       int oldCellIdM1=n2oM1Ptr[i];
1029       if(!isImpacted[oldCellIdM1])
1030         {
1031           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1032           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1033         }
1034       else
1035         {
1036           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1037             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1038           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1039           commonCellsIPtr++;
1040         }
1041     }
1042   //
1043   return ret2.retn();
1044 }
1045
1046 struct MEDCouplingAccVisit
1047 {
1048   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1049   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1050   int _new_nb_of_nodes;
1051 };
1052
1053 /// @endcond
1054
1055 /*!
1056  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1057  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1058  * array of cell ids. Pay attention that after conversion all algorithms work slower
1059  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1060  * conversion due presence of invalid ids in the array of cells to convert, as a
1061  * result \a this mesh contains some already converted elements. In this case the 2D
1062  * mesh remains valid but 3D mesh becomes \b inconsistent!
1063  *  \warning This method can significantly modify the order of geometric types in \a this,
1064  *          hence, to write this mesh to the MED file, its cells must be sorted using
1065  *          sortCellsInMEDFileFrmt().
1066  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1067  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1068  *         cellIdsToConvertBg.
1069  *  \throw If the coordinates array is not set.
1070  *  \throw If the nodal connectivity of cells is node defined.
1071  *  \throw If dimension of \a this mesh is not either 2 or 3.
1072  *
1073  *  \if ENABLE_EXAMPLES
1074  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1075  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1076  *  \endif
1077  */
1078 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1079 {
1080   checkFullyDefined();
1081   int dim=getMeshDimension();
1082   if(dim<2 || dim>3)
1083     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1084   int nbOfCells(getNumberOfCells());
1085   if(dim==2)
1086     {
1087       const int *connIndex=_nodal_connec_index->getConstPointer();
1088       int *conn=_nodal_connec->getPointer();
1089       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1090         {
1091           if(*iter>=0 && *iter<nbOfCells)
1092             {
1093               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1094               if(!cm.isQuadratic())
1095                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1096               else
1097                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1098             }
1099           else
1100             {
1101               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1102               oss << " in range [0," << nbOfCells << ") !";
1103               throw INTERP_KERNEL::Exception(oss.str().c_str());
1104             }
1105         }
1106     }
1107   else
1108     {
1109       int *connIndex(_nodal_connec_index->getPointer());
1110       const int *connOld(_nodal_connec->getConstPointer());
1111       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1112       std::vector<bool> toBeDone(nbOfCells,false);
1113       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1114         {
1115           if(*iter>=0 && *iter<nbOfCells)
1116             toBeDone[*iter]=true;
1117           else
1118             {
1119               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1120               oss << " in range [0," << nbOfCells << ") !";
1121               throw INTERP_KERNEL::Exception(oss.str().c_str());
1122             }
1123         }
1124       for(int cellId=0;cellId<nbOfCells;cellId++)
1125         {
1126           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1127           int lgthOld(posP1-pos-1);
1128           if(toBeDone[cellId])
1129             {
1130               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1131               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1132               int *tmp(new int[nbOfFaces*lgthOld+1]);
1133               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1134               for(unsigned j=0;j<nbOfFaces;j++)
1135                 {
1136                   INTERP_KERNEL::NormalizedCellType type;
1137                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1138                   work+=offset;
1139                   *work++=-1;
1140                 }
1141               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1142               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1143               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1144               delete [] tmp;
1145             }
1146           else
1147             {
1148               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1149               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1150             }
1151         }
1152       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1153     }
1154   computeTypes();
1155 }
1156
1157 /*!
1158  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1159  * polyhedrons (if \a this is a 3D mesh).
1160  *  \warning As this method is purely for user-friendliness and no optimization is
1161  *          done to avoid construction of a useless vector, this method can be costly
1162  *          in memory.
1163  *  \throw If the coordinates array is not set.
1164  *  \throw If the nodal connectivity of cells is node defined.
1165  *  \throw If dimension of \a this mesh is not either 2 or 3.
1166  */
1167 void MEDCouplingUMesh::convertAllToPoly()
1168 {
1169   int nbOfCells=getNumberOfCells();
1170   std::vector<int> cellIds(nbOfCells);
1171   for(int i=0;i<nbOfCells;i++)
1172     cellIds[i]=i;
1173   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1174 }
1175
1176 /*!
1177  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1178  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1179  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1180  * base facet of the volume and the second half of nodes describes an opposite facet
1181  * having the same number of nodes as the base one. This method converts such
1182  * connectivity to a valid polyhedral format where connectivity of each facet is
1183  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1184  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1185  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1186  * a correct orientation of the first facet of a polyhedron, else orientation of a
1187  * corrected cell is reverse.<br>
1188  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1189  * it releases the user from boring description of polyhedra connectivity in the valid
1190  * format.
1191  *  \throw If \a this->getMeshDimension() != 3.
1192  *  \throw If \a this->getSpaceDimension() != 3.
1193  *  \throw If the nodal connectivity of cells is not defined.
1194  *  \throw If the coordinates array is not set.
1195  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1196  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1197  *
1198  *  \if ENABLE_EXAMPLES
1199  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1200  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1201  *  \endif
1202  */
1203 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1204 {
1205   checkFullyDefined();
1206   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1207     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1208   int nbOfCells=getNumberOfCells();
1209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1210   newCi->alloc(nbOfCells+1,1);
1211   int *newci=newCi->getPointer();
1212   const int *ci=_nodal_connec_index->getConstPointer();
1213   const int *c=_nodal_connec->getConstPointer();
1214   newci[0]=0;
1215   for(int i=0;i<nbOfCells;i++)
1216     {
1217       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1218       if(type==INTERP_KERNEL::NORM_POLYHED)
1219         {
1220           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1221             {
1222               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1223               throw INTERP_KERNEL::Exception(oss.str().c_str());
1224             }
1225           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1226           if(n2%2!=0)
1227             {
1228               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron with 1 face but there is a mismatch of number of nodes in face should be even !";
1229               throw INTERP_KERNEL::Exception(oss.str().c_str());
1230             }
1231           int n1=(int)(n2/2);
1232           newci[i+1]=7*n1+2+newci[i];//6*n1 (nodal length) + n1+2 (number of faces) - 1 (number of '-1' separator is equal to number of faces -1) + 1 (for cell type)
1233         }
1234       else
1235         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1236     }
1237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1238   newC->alloc(newci[nbOfCells],1);
1239   int *newc=newC->getPointer();
1240   for(int i=0;i<nbOfCells;i++)
1241     {
1242       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1243       if(type==INTERP_KERNEL::NORM_POLYHED)
1244         {
1245           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1246           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1247           *newc++=-1;
1248           for(std::size_t j=0;j<n1;j++)
1249             {
1250               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1251               newc[n1+5*j]=-1;
1252               newc[n1+5*j+1]=c[ci[i]+1+j];
1253               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1254               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1255               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1256             }
1257           newc+=n1*6;
1258         }
1259       else
1260         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1261     }
1262   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1263   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1264 }
1265
1266
1267 /*!
1268  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1269  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1270  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1271  *          to write this mesh to the MED file, its cells must be sorted using
1272  *          sortCellsInMEDFileFrmt().
1273  * \return \c true if at least one cell has been converted, \c false else. In the
1274  *         last case the nodal connectivity remains unchanged.
1275  * \throw If the coordinates array is not set.
1276  * \throw If the nodal connectivity of cells is not defined.
1277  * \throw If \a this->getMeshDimension() < 0.
1278  */
1279 bool MEDCouplingUMesh::unPolyze()
1280 {
1281   checkFullyDefined();
1282   int mdim=getMeshDimension();
1283   if(mdim<0)
1284     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1285   if(mdim<=1)
1286     return false;
1287   int nbOfCells=getNumberOfCells();
1288   if(nbOfCells<1)
1289     return false;
1290   int initMeshLgth=getMeshLength();
1291   int *conn=_nodal_connec->getPointer();
1292   int *index=_nodal_connec_index->getPointer();
1293   int posOfCurCell=0;
1294   int newPos=0;
1295   int lgthOfCurCell;
1296   bool ret=false;
1297   for(int i=0;i<nbOfCells;i++)
1298     {
1299       lgthOfCurCell=index[i+1]-posOfCurCell;
1300       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1301       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1302       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1303       int newLgth;
1304       if(cm.isDynamic())
1305         {
1306           switch(cm.getDimension())
1307           {
1308             case 2:
1309               {
1310                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1311                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1312                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1313                 break;
1314               }
1315             case 3:
1316               {
1317                 int nbOfFaces,lgthOfPolyhConn;
1318                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1319                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1320                 break;
1321               }
1322             case 1:
1323               {
1324                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1325                 break;
1326               }
1327           }
1328           ret=ret || (newType!=type);
1329           conn[newPos]=newType;
1330           newPos+=newLgth+1;
1331           posOfCurCell=index[i+1];
1332           index[i+1]=newPos;
1333         }
1334       else
1335         {
1336           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1337           newPos+=lgthOfCurCell;
1338           posOfCurCell+=lgthOfCurCell;
1339           index[i+1]=newPos;
1340         }
1341     }
1342   if(newPos!=initMeshLgth)
1343     _nodal_connec->reAlloc(newPos);
1344   if(ret)
1345     computeTypes();
1346   return ret;
1347 }
1348
1349 /*!
1350  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1351  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1352  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1353  *
1354  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not. This epsilon is used to recenter around origin to have maximal 
1355  *             precision.
1356  */
1357 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1358 {
1359   checkFullyDefined();
1360   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1361     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1362   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1363   coords->recenterForMaxPrecision(eps);
1364   //
1365   int nbOfCells=getNumberOfCells();
1366   const int *conn=_nodal_connec->getConstPointer();
1367   const int *index=_nodal_connec_index->getConstPointer();
1368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1369   connINew->alloc(nbOfCells+1,1);
1370   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1371   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1372   bool changed=false;
1373   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1374     {
1375       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1376         {
1377           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1378           changed=true;
1379         }
1380       else
1381         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1382       *connINewPtr=connNew->getNumberOfTuples();
1383     }
1384   if(changed)
1385     setConnectivity(connNew,connINew,false);
1386 }
1387
1388 /*!
1389  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1390  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1391  * the format of returned DataArrayInt instance.
1392  * 
1393  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1394  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
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, areAllNodesFetched
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  *  \sa areAllNodesFetched
1583  *
1584  *  \if ENABLE_EXAMPLES
1585  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1586  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1587  *  \endif
1588  */
1589 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1590 {
1591   return MEDCouplingPointSet::zipCoordsTraducer();
1592 }
1593
1594 /*!
1595  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1596  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1597  */
1598 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1599 {
1600   switch(compType)
1601   {
1602     case 0:
1603       return AreCellsEqual0(conn,connI,cell1,cell2);
1604     case 1:
1605       return AreCellsEqual1(conn,connI,cell1,cell2);
1606     case 2:
1607       return AreCellsEqual2(conn,connI,cell1,cell2);
1608     case 3:
1609       return AreCellsEqual3(conn,connI,cell1,cell2);
1610     case 7:
1611       return AreCellsEqual7(conn,connI,cell1,cell2);
1612   }
1613   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1614 }
1615
1616 /*!
1617  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1618  */
1619 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1620 {
1621   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1622     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1623   return 0;
1624 }
1625
1626 /*!
1627  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1628  */
1629 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1630 {
1631   int sz=connI[cell1+1]-connI[cell1];
1632   if(sz==connI[cell2+1]-connI[cell2])
1633     {
1634       if(conn[connI[cell1]]==conn[connI[cell2]])
1635         {
1636           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1637           unsigned dim=cm.getDimension();
1638           if(dim!=3)
1639             {
1640               if(dim!=1)
1641                 {
1642                   int sz1=2*(sz-1);
1643                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1644                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1645                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1646                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1647                   return work!=tmp+sz1?1:0;
1648                 }
1649               else
1650                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1651             }
1652           else
1653             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1654         }
1655     }
1656   return 0;
1657 }
1658
1659 /*!
1660  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1661  */
1662 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1663 {
1664   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1665     {
1666       if(conn[connI[cell1]]==conn[connI[cell2]])
1667         {
1668           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1669           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1670           return s1==s2?1:0;
1671         }
1672     }
1673   return 0;
1674 }
1675
1676 /*!
1677  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1678  */
1679 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1680 {
1681   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1682     {
1683       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1684       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1685       return s1==s2?1:0;
1686     }
1687   return 0;
1688 }
1689
1690 /*!
1691  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1692  */
1693 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1694 {
1695   int sz=connI[cell1+1]-connI[cell1];
1696   if(sz==connI[cell2+1]-connI[cell2])
1697     {
1698       if(conn[connI[cell1]]==conn[connI[cell2]])
1699         {
1700           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1701           unsigned dim=cm.getDimension();
1702           if(dim!=3)
1703             {
1704               if(dim!=1)
1705                 {
1706                   int sz1=2*(sz-1);
1707                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1708                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1709                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1710                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1711                   if(work!=tmp+sz1)
1712                     return 1;
1713                   else
1714                     {
1715                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1716                       std::reverse_iterator<int *> it2((int *)tmp);
1717                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1718                         return 2;
1719                       else
1720                         return 0;
1721                     }
1722
1723                   return work!=tmp+sz1?1:0;
1724                 }
1725               else
1726                 {//case of SEG2 and SEG3
1727                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1728                     return 1;
1729                   if(!cm.isQuadratic())
1730                     {
1731                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1732                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1733                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1734                         return 2;
1735                       return 0;
1736                     }
1737                   else
1738                     {
1739                       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])
1740                         return 2;
1741                       return 0;
1742                     }
1743                 }
1744             }
1745           else
1746             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1747         }
1748     }
1749   return 0;
1750 }
1751
1752 /*!
1753  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1754  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1755  * and result remains unchanged.
1756  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1757  * If in 'candidates' pool -1 value is considered as an empty value.
1758  * WARNING this method returns only ONE set of result !
1759  */
1760 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1761 {
1762   if(candidates.size()<1)
1763     return false;
1764   bool ret=false;
1765   std::vector<int>::const_iterator iter=candidates.begin();
1766   int start=(*iter++);
1767   for(;iter!=candidates.end();iter++)
1768     {
1769       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1770       if(status!=0)
1771         {
1772           if(!ret)
1773             {
1774               result->pushBackSilent(start);
1775               ret=true;
1776             }
1777           if(status==1)
1778             result->pushBackSilent(*iter);
1779           else
1780             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1781         }
1782     }
1783   return ret;
1784 }
1785
1786 /*!
1787  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1788  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1789  *
1790  * \param [in] compType input specifying the technique used to compare cells each other.
1791  *   - 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.
1792  *   - 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)
1793  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1794  *   - 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
1795  * can be used for users not sensitive to orientation of cell
1796  * \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.
1797  * \param [out] commonCells
1798  * \param [out] commonCellsI
1799  * \return the correspondance array old to new in a newly allocated array.
1800  * 
1801  */
1802 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1803 {
1804   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1805   getReverseNodalConnectivity(revNodal,revNodalI);
1806   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1807 }
1808
1809 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1810                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1811 {
1812   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1813   int nbOfCells=nodalI->getNumberOfTuples()-1;
1814   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1815   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1816   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1817   std::vector<bool> isFetched(nbOfCells,false);
1818   if(startCellId==0)
1819     {
1820       for(int i=0;i<nbOfCells;i++)
1821         {
1822           if(!isFetched[i])
1823             {
1824               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1825               std::vector<int> v,v2;
1826               if(connOfNode!=connPtr+connIPtr[i+1])
1827                 {
1828                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1829                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1830                   connOfNode++;
1831                 }
1832               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1833                 if(*connOfNode>=0)
1834                   {
1835                     v=v2;
1836                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1837                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1838                     v2.resize(std::distance(v2.begin(),it));
1839                   }
1840               if(v2.size()>1)
1841                 {
1842                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1843                     {
1844                       int pos=commonCellsI->back();
1845                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1846                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1847                         isFetched[*it]=true;
1848                     }
1849                 }
1850             }
1851         }
1852     }
1853   else
1854     {
1855       for(int i=startCellId;i<nbOfCells;i++)
1856         {
1857           if(!isFetched[i])
1858             {
1859               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1860               std::vector<int> v,v2;
1861               if(connOfNode!=connPtr+connIPtr[i+1])
1862                 {
1863                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1864                   connOfNode++;
1865                 }
1866               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1867                 if(*connOfNode>=0)
1868                   {
1869                     v=v2;
1870                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1871                     v2.resize(std::distance(v2.begin(),it));
1872                   }
1873               if(v2.size()>1)
1874                 {
1875                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1876                     {
1877                       int pos=commonCellsI->back();
1878                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1879                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1880                         isFetched[*it]=true;
1881                     }
1882                 }
1883             }
1884         }
1885     }
1886   commonCellsArr=commonCells.retn();
1887   commonCellsIArr=commonCellsI.retn();
1888 }
1889
1890 /*!
1891  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1892  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1893  * than \a other->getNumberOfCells() in the returned array means that there is no
1894  * corresponding cell in \a this mesh.
1895  * It is expected that \a this and \a other meshes share the same node coordinates
1896  * array, if it is not so an exception is thrown. 
1897  *  \param [in] other - the mesh to compare with.
1898  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1899  *         valid values [0,1,2], see zipConnectivityTraducer().
1900  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1901  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1902  *         values. The caller is to delete this array using
1903  *         decrRef() as it is no more needed.
1904  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1905  *         mesh.
1906  *
1907  *  \if ENABLE_EXAMPLES
1908  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1909  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1910  *  \endif
1911  *  \sa checkDeepEquivalOnSameNodesWith()
1912  *  \sa checkGeoEquivalWith()
1913  */
1914 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1915 {
1916   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1917   int nbOfCells=getNumberOfCells();
1918   static const int possibleCompType[]={0,1,2};
1919   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1920     {
1921       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1922       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1923       oss << " !";
1924       throw INTERP_KERNEL::Exception(oss.str().c_str());
1925     }
1926   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1927   arr=o2n->substr(nbOfCells);
1928   arr->setName(other->getName());
1929   int tmp;
1930   if(other->getNumberOfCells()==0)
1931     return true;
1932   return arr->getMaxValue(tmp)<nbOfCells;
1933 }
1934
1935 /*!
1936  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1937  * This method tries to determine if \b other is fully included in \b this.
1938  * The main difference is that this method is not expected to throw exception.
1939  * This method has two outputs :
1940  *
1941  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1942  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1943  */
1944 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1945 {
1946   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1947   DataArrayInt *commonCells=0,*commonCellsI=0;
1948   int thisNbCells=getNumberOfCells();
1949   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1950   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1951   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1952   int otherNbCells=other->getNumberOfCells();
1953   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1954   arr2->alloc(otherNbCells,1);
1955   arr2->fillWithZero();
1956   int *arr2Ptr=arr2->getPointer();
1957   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1958   for(int i=0;i<nbOfCommon;i++)
1959     {
1960       int start=commonCellsPtr[commonCellsIPtr[i]];
1961       if(start<thisNbCells)
1962         {
1963           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1964             {
1965               int sig=commonCellsPtr[j]>0?1:-1;
1966               int val=std::abs(commonCellsPtr[j])-1;
1967               if(val>=thisNbCells)
1968                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1969             }
1970         }
1971     }
1972   arr2->setName(other->getName());
1973   if(arr2->presenceOfValue(0))
1974     return false;
1975   arr=arr2.retn();
1976   return true;
1977 }
1978
1979 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1980 {
1981   if(!other)
1982     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1983   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1984   if(!otherC)
1985     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1986   std::vector<const MEDCouplingUMesh *> ms(2);
1987   ms[0]=this;
1988   ms[1]=otherC;
1989   return MergeUMeshesOnSameCoords(ms);
1990 }
1991
1992 /*!
1993  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1994  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1995  * cellIds is not given explicitely but by a range python like.
1996  * 
1997  * \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.
1998  * \return a newly allocated
1999  * 
2000  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2001  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2002  */
2003 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2004 {
2005   if(getMeshDimension()!=-1)
2006     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2007   else
2008     {
2009       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2010       if(newNbOfCells!=1)
2011         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2012       if(start!=0)
2013         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2014       incrRef();
2015       return const_cast<MEDCouplingUMesh *>(this);
2016     }
2017 }
2018
2019 /*!
2020  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2021  * The result mesh shares or not the node coordinates array with \a this mesh depending
2022  * on \a keepCoords parameter.
2023  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2024  *           to write this mesh to the MED file, its cells must be sorted using
2025  *           sortCellsInMEDFileFrmt().
2026  *  \param [in] begin - an array of cell ids to include to the new mesh.
2027  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2028  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2029  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2030  *         by calling zipCoords().
2031  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2032  *         to delete this mesh using decrRef() as it is no more needed. 
2033  *  \throw If the coordinates array is not set.
2034  *  \throw If the nodal connectivity of cells is not defined.
2035  *  \throw If any cell id in the array \a begin is not valid.
2036  *
2037  *  \if ENABLE_EXAMPLES
2038  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2039  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2040  *  \endif
2041  */
2042 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2043 {
2044   if(getMeshDimension()!=-1)
2045     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2046   else
2047     {
2048       if(end-begin!=1)
2049         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2050       if(begin[0]!=0)
2051         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2052       incrRef();
2053       return const_cast<MEDCouplingUMesh *>(this);
2054     }
2055 }
2056
2057 /*!
2058  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2059  *
2060  * 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.
2061  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2062  * The number of cells of \b this will remain the same with this method.
2063  *
2064  * \param [in] begin begin of cell ids (included) of cells in this to assign
2065  * \param [in] end end of cell ids (excluded) of cells in this to assign
2066  * \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 ).
2067  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2068  */
2069 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2070 {
2071   checkConnectivityFullyDefined();
2072   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2073   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2074     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2075   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2076     {
2077       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2078       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2079       throw INTERP_KERNEL::Exception(oss.str().c_str());
2080     }
2081   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2082   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2083     {
2084       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2085       throw INTERP_KERNEL::Exception(oss.str().c_str());
2086     }
2087   int nbOfCells=getNumberOfCells();
2088   bool easyAssign=true;
2089   const int *connI=_nodal_connec_index->getConstPointer();
2090   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2091   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2092     {
2093       if(*it>=0 && *it<nbOfCells)
2094         {
2095           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2096         }
2097       else
2098         {
2099           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2100           throw INTERP_KERNEL::Exception(oss.str().c_str());
2101         }
2102     }
2103   if(easyAssign)
2104     {
2105       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2106       computeTypes();
2107     }
2108   else
2109     {
2110       DataArrayInt *arrOut=0,*arrIOut=0;
2111       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2112                                                arrOut,arrIOut);
2113       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2114       setConnectivity(arrOut,arrIOut,true);
2115     }
2116 }
2117
2118 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2119 {
2120   checkConnectivityFullyDefined();
2121   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2122   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2123     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2124   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2125     {
2126       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2127       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2128       throw INTERP_KERNEL::Exception(oss.str().c_str());
2129     }
2130   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2131   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2132     {
2133       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2134       throw INTERP_KERNEL::Exception(oss.str().c_str());
2135     }
2136   int nbOfCells=getNumberOfCells();
2137   bool easyAssign=true;
2138   const int *connI=_nodal_connec_index->getConstPointer();
2139   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2140   int it=start;
2141   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2142     {
2143       if(it>=0 && it<nbOfCells)
2144         {
2145           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2146         }
2147       else
2148         {
2149           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2150           throw INTERP_KERNEL::Exception(oss.str().c_str());
2151         }
2152     }
2153   if(easyAssign)
2154     {
2155       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2156       computeTypes();
2157     }
2158   else
2159     {
2160       DataArrayInt *arrOut=0,*arrIOut=0;
2161       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2162                                                 arrOut,arrIOut);
2163       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2164       setConnectivity(arrOut,arrIOut,true);
2165     }
2166 }                      
2167
2168 /*!
2169  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2170  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2171  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2172  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2173  *
2174  * \param [in] begin input start of array of node ids.
2175  * \param [in] end input end of array of node ids.
2176  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2177  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2178  */
2179 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2180 {
2181   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2182   checkConnectivityFullyDefined();
2183   int tmp=-1;
2184   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2185   std::vector<bool> fastFinder(sz,false);
2186   for(const int *work=begin;work!=end;work++)
2187     if(*work>=0 && *work<sz)
2188       fastFinder[*work]=true;
2189   int nbOfCells=getNumberOfCells();
2190   const int *conn=getNodalConnectivity()->getConstPointer();
2191   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2192   for(int i=0;i<nbOfCells;i++)
2193     {
2194       int ref=0,nbOfHit=0;
2195       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2196         if(*work2>=0)
2197           {
2198             ref++;
2199             if(fastFinder[*work2])
2200               nbOfHit++;
2201           }
2202       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2203         cellIdsKept->pushBackSilent(i);
2204     }
2205   cellIdsKeptArr=cellIdsKept.retn();
2206 }
2207
2208 /*!
2209  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2210  * this->getMeshDimension(), that bound some cells of \a this mesh.
2211  * The cells of lower dimension to include to the result mesh are selected basing on
2212  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2213  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2214  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2215  * created mesh shares the node coordinates array with \a this mesh. 
2216  *  \param [in] begin - the array of node ids.
2217  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2218  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2219  *         array \a begin are added, else cells whose any node is in the
2220  *         array \a begin are added.
2221  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2222  *         to delete this mesh using decrRef() as it is no more needed. 
2223  *  \throw If the coordinates array is not set.
2224  *  \throw If the nodal connectivity of cells is not defined.
2225  *  \throw If any node id in \a begin is not valid.
2226  *
2227  *  \if ENABLE_EXAMPLES
2228  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2229  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2230  *  \endif
2231  */
2232 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2233 {
2234   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2235   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2236   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2237   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2238   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2239 }
2240
2241 /*!
2242  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2243  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2244  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2245  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2246  *         by calling zipCoords().
2247  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2248  *         to delete this mesh using decrRef() as it is no more needed. 
2249  *  \throw If the coordinates array is not set.
2250  *  \throw If the nodal connectivity of cells is not defined.
2251  *
2252  *  \if ENABLE_EXAMPLES
2253  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2254  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2255  *  \endif
2256  */
2257 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2258 {
2259   DataArrayInt *desc=DataArrayInt::New();
2260   DataArrayInt *descIndx=DataArrayInt::New();
2261   DataArrayInt *revDesc=DataArrayInt::New();
2262   DataArrayInt *revDescIndx=DataArrayInt::New();
2263   //
2264   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2265   revDesc->decrRef();
2266   desc->decrRef();
2267   descIndx->decrRef();
2268   int nbOfCells=meshDM1->getNumberOfCells();
2269   const int *revDescIndxC=revDescIndx->getConstPointer();
2270   std::vector<int> boundaryCells;
2271   for(int i=0;i<nbOfCells;i++)
2272     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2273       boundaryCells.push_back(i);
2274   revDescIndx->decrRef();
2275   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2276   return ret;
2277 }
2278
2279 /*!
2280  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2281  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2282  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2283  */
2284 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2285 {
2286   checkFullyDefined();
2287   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2288   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2290   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2291   //
2292   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2293   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2294   //
2295   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2296   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2297   const int *revDescPtr=revDesc->getConstPointer();
2298   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2299   int nbOfCells=getNumberOfCells();
2300   std::vector<bool> ret1(nbOfCells,false);
2301   int sz=0;
2302   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2303     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2304       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2305   //
2306   DataArrayInt *ret2=DataArrayInt::New();
2307   ret2->alloc(sz,1);
2308   int *ret2Ptr=ret2->getPointer();
2309   sz=0;
2310   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2311     if(*it)
2312       *ret2Ptr++=sz;
2313   ret2->setName("BoundaryCells");
2314   return ret2;
2315 }
2316
2317 /*!
2318  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2319  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2320  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2321  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2322  *
2323  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2324  * This method method returns cells ids set s = s1 + s2 where :
2325  * 
2326  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2327  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2328  *
2329  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2330  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2331  *
2332  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2333  * \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
2334  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2335  */
2336 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2337 {
2338   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2339     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2340   checkConnectivityFullyDefined();
2341   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2342   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2343     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2345   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2346   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2348   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2349   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2350   DataArrayInt *idsOtherInConsti=0;
2351   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2352   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2353   if(!b)
2354     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2355   std::set<int> s1;
2356   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2357     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2360   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2361   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2363   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2364   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2365   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2366   neighThisPartAuto=0;
2367   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2368   const int li[2]={0,1};
2369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2370   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2371   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2372   s_renum1->sort();
2373   //
2374   cellIdsRk0=s0arr.retn();
2375   cellIdsRk1=s_renum1.retn();
2376 }
2377
2378 /*!
2379  * 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
2380  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2381  * 
2382  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2383  */
2384 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2385 {
2386   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2387   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2390   //
2391   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2392   revDesc=0; desc=0; descIndx=0;
2393   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2394   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2395   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2396 }
2397
2398 /*!
2399  * Finds nodes lying on the boundary of \a this mesh.
2400  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2401  *          nodes. The caller is to delete this array using decrRef() as it is no
2402  *          more needed.
2403  *  \throw If the coordinates array is not set.
2404  *  \throw If the nodal connectivity of cells is node defined.
2405  *
2406  *  \if ENABLE_EXAMPLES
2407  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2408  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2409  *  \endif
2410  */
2411 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2412 {
2413   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2414   return skin->computeFetchedNodeIds();
2415 }
2416
2417 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2418 {
2419   incrRef();
2420   return const_cast<MEDCouplingUMesh *>(this);
2421 }
2422
2423 /*!
2424  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2425  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2426  * 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.
2427  * 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.
2428  * 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.
2429  *
2430  * \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
2431  *             parameter is altered during the call.
2432  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2433  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2434  * \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.
2435  *
2436  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2437  */
2438 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2439                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2440 {
2441   checkFullyDefined();
2442   otherDimM1OnSameCoords.checkFullyDefined();
2443   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2444     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2445   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2446     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2447   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2448   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2449   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2450   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2451   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2452   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2453   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2454   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2455   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2456   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2457   //
2458   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2460   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2461   DataArrayInt *idsTmp=0;
2462   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2463   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2464   if(!b)
2465     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2466   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2467   DataArrayInt *tmp0=0,*tmp1=0;
2468   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2469   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2472   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2473   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2474   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2475   //
2476   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2477   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2478   nodeIdsToDuplicate=s3.retn();
2479 }
2480
2481 /*!
2482  * This method operates a modification of the connectivity and coords in \b this.
2483  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2484  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2485  * 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
2486  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2487  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2488  * 
2489  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2490  * 
2491  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2492  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2493  */
2494 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2495 {
2496   int nbOfNodes=getNumberOfNodes();
2497   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2498   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2499 }
2500
2501 /*!
2502  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2503  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2504  *
2505  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2506  *
2507  * \sa renumberNodesInConn
2508  */
2509 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2510 {
2511   checkConnectivityFullyDefined();
2512   int *conn(getNodalConnectivity()->getPointer());
2513   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2514   int nbOfCells(getNumberOfCells());
2515   for(int i=0;i<nbOfCells;i++)
2516     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2517       {
2518         int& node=conn[iconn];
2519         if(node>=0)//avoid polyhedron separator
2520           {
2521             node+=offset;
2522           }
2523       }
2524   _nodal_connec->declareAsNew();
2525   updateTime();
2526 }
2527
2528 /*!
2529  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2530  *  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
2531  *  of a big mesh.
2532  */
2533 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2534 {
2535   checkConnectivityFullyDefined();
2536   int *conn(getNodalConnectivity()->getPointer());
2537   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2538   int nbOfCells(getNumberOfCells());
2539   for(int i=0;i<nbOfCells;i++)
2540     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2541       {
2542         int& node=conn[iconn];
2543         if(node>=0)//avoid polyhedron separator
2544           {
2545             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2546             if(it!=newNodeNumbersO2N.end())
2547               {
2548                 node=(*it).second;
2549               }
2550             else
2551               {
2552                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2553                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2554               }
2555           }
2556       }
2557   _nodal_connec->declareAsNew();
2558   updateTime();
2559 }
2560
2561 /*!
2562  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2563  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2564  * This method is a generalization of shiftNodeNumbersInConn().
2565  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2566  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2567  *         this->getNumberOfNodes(), in "Old to New" mode. 
2568  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2569  *  \throw If the nodal connectivity of cells is not defined.
2570  *
2571  *  \if ENABLE_EXAMPLES
2572  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2573  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2574  *  \endif
2575  */
2576 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2577 {
2578   checkConnectivityFullyDefined();
2579   int *conn=getNodalConnectivity()->getPointer();
2580   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2581   int nbOfCells(getNumberOfCells());
2582   for(int i=0;i<nbOfCells;i++)
2583     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2584       {
2585         int& node=conn[iconn];
2586         if(node>=0)//avoid polyhedron separator
2587           {
2588             node=newNodeNumbersO2N[node];
2589           }
2590       }
2591   _nodal_connec->declareAsNew();
2592   updateTime();
2593 }
2594
2595 /*!
2596  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2597  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2598  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2599  * 
2600  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2601  */
2602 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2603 {
2604   checkConnectivityFullyDefined();
2605   int *conn=getNodalConnectivity()->getPointer();
2606   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2607   int nbOfCells=getNumberOfCells();
2608   for(int i=0;i<nbOfCells;i++)
2609     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2610       {
2611         int& node=conn[iconn];
2612         if(node>=0)//avoid polyhedron separator
2613           {
2614             node+=delta;
2615           }
2616       }
2617   _nodal_connec->declareAsNew();
2618   updateTime();
2619 }
2620
2621 /*!
2622  * This method operates a modification of the connectivity in \b this.
2623  * 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.
2624  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2625  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2626  * 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
2627  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2628  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2629  * 
2630  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2631  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2632  * 
2633  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2634  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2635  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2636  */
2637 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2638 {
2639   checkConnectivityFullyDefined();
2640   std::map<int,int> m;
2641   int val=offset;
2642   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2643     m[*work]=val;
2644   int *conn=getNodalConnectivity()->getPointer();
2645   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2646   int nbOfCells=getNumberOfCells();
2647   for(int i=0;i<nbOfCells;i++)
2648     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2649       {
2650         int& node=conn[iconn];
2651         if(node>=0)//avoid polyhedron separator
2652           {
2653             std::map<int,int>::iterator it=m.find(node);
2654             if(it!=m.end())
2655               node=(*it).second;
2656           }
2657       }
2658   updateTime();
2659 }
2660
2661 /*!
2662  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2663  *
2664  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2665  * After the call of this method the number of cells remains the same as before.
2666  *
2667  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2668  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2669  * be strictly in [0;this->getNumberOfCells()).
2670  *
2671  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2672  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2673  * should be contained in[0;this->getNumberOfCells()).
2674  * 
2675  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2676  */
2677 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2678 {
2679   checkConnectivityFullyDefined();
2680   int nbCells=getNumberOfCells();
2681   const int *array=old2NewBg;
2682   if(check)
2683     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2684   //
2685   const int *conn=_nodal_connec->getConstPointer();
2686   const int *connI=_nodal_connec_index->getConstPointer();
2687   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2688   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2689   const int *n2oPtr=n2o->begin();
2690   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2691   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2692   newConn->copyStringInfoFrom(*_nodal_connec);
2693   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2694   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2695   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2696   //
2697   int *newC=newConn->getPointer();
2698   int *newCI=newConnI->getPointer();
2699   int loc=0;
2700   newCI[0]=loc;
2701   for(int i=0;i<nbCells;i++)
2702     {
2703       int pos=n2oPtr[i];
2704       int nbOfElts=connI[pos+1]-connI[pos];
2705       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2706       loc+=nbOfElts;
2707       newCI[i+1]=loc;
2708     }
2709   //
2710   setConnectivity(newConn,newConnI);
2711   if(check)
2712     free(const_cast<int *>(array));
2713 }
2714
2715 /*!
2716  * Finds cells whose bounding boxes intersect a given bounding box.
2717  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2718  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2719  *         zMax (if in 3D). 
2720  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2721  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2722  *         extent of the bounding box of cell to produce an addition to this bounding box.
2723  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2724  *         cells. The caller is to delete this array using decrRef() as it is no more
2725  *         needed. 
2726  *  \throw If the coordinates array is not set.
2727  *  \throw If the nodal connectivity of cells is not defined.
2728  *
2729  *  \if ENABLE_EXAMPLES
2730  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2731  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2732  *  \endif
2733  */
2734 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2735 {
2736   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2737   if(getMeshDimension()==-1)
2738     {
2739       elems->pushBackSilent(0);
2740       return elems.retn();
2741     }
2742   int dim=getSpaceDimension();
2743   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2744   const int* conn      = getNodalConnectivity()->getConstPointer();
2745   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2746   const double* coords = getCoords()->getConstPointer();
2747   int nbOfCells=getNumberOfCells();
2748   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2749     {
2750       for (int i=0; i<dim; i++)
2751         {
2752           elem_bb[i*2]=std::numeric_limits<double>::max();
2753           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2754         }
2755
2756       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2757         {
2758           int node= conn[inode];
2759           if(node>=0)//avoid polyhedron separator
2760             {
2761               for (int idim=0; idim<dim; idim++)
2762                 {
2763                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2764                     {
2765                       elem_bb[idim*2] = coords[node*dim+idim] ;
2766                     }
2767                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2768                     {
2769                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2770                     }
2771                 }
2772             }
2773         }
2774       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2775         elems->pushBackSilent(ielem);
2776     }
2777   return elems.retn();
2778 }
2779
2780 /*!
2781  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2782  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2783  * added in 'elems' parameter.
2784  */
2785 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2786 {
2787   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2788   if(getMeshDimension()==-1)
2789     {
2790       elems->pushBackSilent(0);
2791       return elems.retn();
2792     }
2793   int dim=getSpaceDimension();
2794   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2795   const int* conn      = getNodalConnectivity()->getConstPointer();
2796   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2797   const double* coords = getCoords()->getConstPointer();
2798   int nbOfCells=getNumberOfCells();
2799   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2800     {
2801       for (int i=0; i<dim; i++)
2802         {
2803           elem_bb[i*2]=std::numeric_limits<double>::max();
2804           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2805         }
2806
2807       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2808         {
2809           int node= conn[inode];
2810           if(node>=0)//avoid polyhedron separator
2811             {
2812               for (int idim=0; idim<dim; idim++)
2813                 {
2814                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2815                     {
2816                       elem_bb[idim*2] = coords[node*dim+idim] ;
2817                     }
2818                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2819                     {
2820                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2821                     }
2822                 }
2823             }
2824         }
2825       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2826         elems->pushBackSilent(ielem);
2827     }
2828   return elems.retn();
2829 }
2830
2831 /*!
2832  * Returns a type of a cell by its id.
2833  *  \param [in] cellId - the id of the cell of interest.
2834  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2835  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2836  */
2837 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2838 {
2839   const int *ptI=_nodal_connec_index->getConstPointer();
2840   const int *pt=_nodal_connec->getConstPointer();
2841   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2842     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2843   else
2844     {
2845       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2846       throw INTERP_KERNEL::Exception(oss.str().c_str());
2847     }
2848 }
2849
2850 /*!
2851  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2852  * This method does not throw exception if geometric type \a type is not in \a this.
2853  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2854  * The coordinates array is not considered here.
2855  *
2856  * \param [in] type the geometric type
2857  * \return cell ids in this having geometric type \a type.
2858  */
2859 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2860 {
2861
2862   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2863   ret->alloc(0,1);
2864   checkConnectivityFullyDefined();
2865   int nbCells=getNumberOfCells();
2866   int mdim=getMeshDimension();
2867   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2868   if(mdim!=(int)cm.getDimension())
2869     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2870   const int *ptI=_nodal_connec_index->getConstPointer();
2871   const int *pt=_nodal_connec->getConstPointer();
2872   for(int i=0;i<nbCells;i++)
2873     {
2874       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2875         ret->pushBackSilent(i);
2876     }
2877   return ret.retn();
2878 }
2879
2880 /*!
2881  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2882  */
2883 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2884 {
2885   const int *ptI=_nodal_connec_index->getConstPointer();
2886   const int *pt=_nodal_connec->getConstPointer();
2887   int nbOfCells=getNumberOfCells();
2888   int ret=0;
2889   for(int i=0;i<nbOfCells;i++)
2890     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2891       ret++;
2892   return ret;
2893 }
2894
2895 /*!
2896  * Returns the nodal connectivity of a given cell.
2897  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2898  * all returned node ids can be used in getCoordinatesOfNode().
2899  *  \param [in] cellId - an id of the cell of interest.
2900  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2901  *         cleared before the appending.
2902  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2903  */
2904 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2905 {
2906   const int *ptI=_nodal_connec_index->getConstPointer();
2907   const int *pt=_nodal_connec->getConstPointer();
2908   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2909     if(*w>=0)
2910       conn.push_back(*w);
2911 }
2912
2913 std::string MEDCouplingUMesh::simpleRepr() const
2914 {
2915   static const char msg0[]="No coordinates specified !";
2916   std::ostringstream ret;
2917   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2918   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2919   int tmpp1,tmpp2;
2920   double tt=getTime(tmpp1,tmpp2);
2921   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2922   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2923   if(_mesh_dim>=-1)
2924     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2925   else
2926     { ret << " Mesh dimension has not been set or is invalid !"; }
2927   if(_coords!=0)
2928     {
2929       const int spaceDim=getSpaceDimension();
2930       ret << spaceDim << "\nInfo attached on space dimension : ";
2931       for(int i=0;i<spaceDim;i++)
2932         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2933       ret << "\n";
2934     }
2935   else
2936     ret << msg0 << "\n";
2937   ret << "Number of nodes : ";
2938   if(_coords!=0)
2939     ret << getNumberOfNodes() << "\n";
2940   else
2941     ret << msg0 << "\n";
2942   ret << "Number of cells : ";
2943   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2944     ret << getNumberOfCells() << "\n";
2945   else
2946     ret << "No connectivity specified !" << "\n";
2947   ret << "Cell types present : ";
2948   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2949     {
2950       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2951       ret << cm.getRepr() << " ";
2952     }
2953   ret << "\n";
2954   return ret.str();
2955 }
2956
2957 std::string MEDCouplingUMesh::advancedRepr() const
2958 {
2959   std::ostringstream ret;
2960   ret << simpleRepr();
2961   ret << "\nCoordinates array : \n___________________\n\n";
2962   if(_coords)
2963     _coords->reprWithoutNameStream(ret);
2964   else
2965     ret << "No array set !\n";
2966   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2967   reprConnectivityOfThisLL(ret);
2968   return ret.str();
2969 }
2970
2971 /*!
2972  * This method returns a C++ code that is a dump of \a this.
2973  * This method will throw if this is not fully defined.
2974  */
2975 std::string MEDCouplingUMesh::cppRepr() const
2976 {
2977   static const char coordsName[]="coords";
2978   static const char connName[]="conn";
2979   static const char connIName[]="connI";
2980   checkFullyDefined();
2981   std::ostringstream ret; ret << "// coordinates" << std::endl;
2982   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2983   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2984   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2985   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2986   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2987   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2988   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2989   return ret.str();
2990 }
2991
2992 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2993 {
2994   std::ostringstream ret;
2995   reprConnectivityOfThisLL(ret);
2996   return ret.str();
2997 }
2998
2999 /*!
3000  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3001  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3002  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3003  * some algos).
3004  * 
3005  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3006  * 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
3007  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3008  */
3009 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3010 {
3011   int mdim=getMeshDimension();
3012   if(mdim<0)
3013     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3014   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3015   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3016   bool needToCpyCT=true;
3017   if(!_nodal_connec)
3018     {
3019       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3020       needToCpyCT=false;
3021     }
3022   else
3023     {
3024       tmp1=_nodal_connec;
3025       tmp1->incrRef();
3026     }
3027   if(!_nodal_connec_index)
3028     {
3029       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3030       needToCpyCT=false;
3031     }
3032   else
3033     {
3034       tmp2=_nodal_connec_index;
3035       tmp2->incrRef();
3036     }
3037   ret->setConnectivity(tmp1,tmp2,false);
3038   if(needToCpyCT)
3039     ret->_types=_types;
3040   if(!_coords)
3041     {
3042       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3043       ret->setCoords(coords);
3044     }
3045   else
3046     ret->setCoords(_coords);
3047   return ret.retn();
3048 }
3049
3050 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3051 {
3052   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3053     {
3054       int nbOfCells=getNumberOfCells();
3055       const int *c=_nodal_connec->getConstPointer();
3056       const int *ci=_nodal_connec_index->getConstPointer();
3057       for(int i=0;i<nbOfCells;i++)
3058         {
3059           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3060           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3061           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3062           stream << "\n";
3063         }
3064     }
3065   else
3066     stream << "Connectivity not defined !\n";
3067 }
3068
3069 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3070 {
3071   const int *ptI=_nodal_connec_index->getConstPointer();
3072   const int *pt=_nodal_connec->getConstPointer();
3073   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3074     return ptI[cellId+1]-ptI[cellId]-1;
3075   else
3076     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3077 }
3078
3079 /*!
3080  * Returns types of cells of the specified part of \a this mesh.
3081  * This method avoids computing sub-mesh explicitely to get its types.
3082  *  \param [in] begin - an array of cell ids of interest.
3083  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3084  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3085  *         describing the cell types. 
3086  *  \throw If the coordinates array is not set.
3087  *  \throw If the nodal connectivity of cells is not defined.
3088  *  \sa getAllGeoTypes()
3089  */
3090 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3091 {
3092   checkFullyDefined();
3093   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3094   const int *conn=_nodal_connec->getConstPointer();
3095   const int *connIndex=_nodal_connec_index->getConstPointer();
3096   for(const int *w=begin;w!=end;w++)
3097     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3098   return ret;
3099 }
3100
3101 /*!
3102  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3103  * a set of types of cells constituting \a this mesh. 
3104  * This method is for advanced users having prepared their connectivity before. For
3105  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3106  *  \param [in] conn - the nodal connectivity array. 
3107  *  \param [in] connIndex - the nodal connectivity index array.
3108  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3109  *         mesh is updated.
3110  */
3111 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3112 {
3113   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3114   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3115   if(isComputingTypes)
3116     computeTypes();
3117   declareAsNew();
3118 }
3119
3120 /*!
3121  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3122  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3123  */
3124 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3125     _nodal_connec(0),_nodal_connec_index(0),
3126     _types(other._types)
3127 {
3128   if(other._nodal_connec)
3129     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3130   if(other._nodal_connec_index)
3131     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3132 }
3133
3134 MEDCouplingUMesh::~MEDCouplingUMesh()
3135 {
3136   if(_nodal_connec)
3137     _nodal_connec->decrRef();
3138   if(_nodal_connec_index)
3139     _nodal_connec_index->decrRef();
3140 }
3141
3142 /*!
3143  * Recomputes a set of cell types of \a this mesh. For more info see
3144  * \ref MEDCouplingUMeshNodalConnectivity.
3145  */
3146 void MEDCouplingUMesh::computeTypes()
3147 {
3148   if(_nodal_connec && _nodal_connec_index)
3149     {
3150       _types.clear();
3151       const int *conn=_nodal_connec->getConstPointer();
3152       const int *connIndex=_nodal_connec_index->getConstPointer();
3153       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3154       if (nbOfElem > 0)
3155         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3156           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3157     }
3158 }
3159
3160 /*!
3161  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3162  */
3163 void MEDCouplingUMesh::checkFullyDefined() const
3164 {
3165   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3166     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3167 }
3168
3169 /*!
3170  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3171  */
3172 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3173 {
3174   if(!_nodal_connec_index || !_nodal_connec)
3175     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3176 }
3177
3178 /*!
3179  * Returns a number of cells constituting \a this mesh. 
3180  *  \return int - the number of cells in \a this mesh.
3181  *  \throw If the nodal connectivity of cells is not defined.
3182  */
3183 int MEDCouplingUMesh::getNumberOfCells() const
3184
3185   if(_nodal_connec_index)
3186     return _nodal_connec_index->getNumberOfTuples()-1;
3187   else
3188     if(_mesh_dim==-1)
3189       return 1;
3190     else
3191       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3192 }
3193
3194 /*!
3195  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3196  * mesh. For more info see \ref MEDCouplingMeshesPage.
3197  *  \return int - the dimension of \a this mesh.
3198  *  \throw If the mesh dimension is not defined using setMeshDimension().
3199  */
3200 int MEDCouplingUMesh::getMeshDimension() const
3201 {
3202   if(_mesh_dim<-1)
3203     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3204   return _mesh_dim;
3205 }
3206
3207 /*!
3208  * Returns a length of the nodal connectivity array.
3209  * This method is for test reason. Normally the integer returned is not useable by
3210  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3211  *  \return int - the length of the nodal connectivity array.
3212  */
3213 int MEDCouplingUMesh::getMeshLength() const
3214 {
3215   return _nodal_connec->getNbOfElems();
3216 }
3217
3218 /*!
3219  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3220  */
3221 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3222 {
3223   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3224   tinyInfo.push_back(getMeshDimension());
3225   tinyInfo.push_back(getNumberOfCells());
3226   if(_nodal_connec)
3227     tinyInfo.push_back(getMeshLength());
3228   else
3229     tinyInfo.push_back(-1);
3230 }
3231
3232 /*!
3233  * First step of unserialization process.
3234  */
3235 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3236 {
3237   return tinyInfo[6]<=0;
3238 }
3239
3240 /*!
3241  * Second step of serialization process.
3242  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3243  */
3244 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3245 {
3246   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3247   if(tinyInfo[5]!=-1)
3248     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3249 }
3250
3251 /*!
3252  * Third and final step of serialization process.
3253  */
3254 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3255 {
3256   MEDCouplingPointSet::serialize(a1,a2);
3257   if(getMeshDimension()>-1)
3258     {
3259       a1=DataArrayInt::New();
3260       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3261       int *ptA1=a1->getPointer();
3262       const int *conn=getNodalConnectivity()->getConstPointer();
3263       const int *index=getNodalConnectivityIndex()->getConstPointer();
3264       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3265       std::copy(conn,conn+getMeshLength(),ptA1);
3266     }
3267   else
3268     a1=0;
3269 }
3270
3271 /*!
3272  * Second and final unserialization process.
3273  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3274  */
3275 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3276 {
3277   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3278   setMeshDimension(tinyInfo[5]);
3279   if(tinyInfo[7]!=-1)
3280     {
3281       // Connectivity
3282       const int *recvBuffer=a1->getConstPointer();
3283       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3284       myConnecIndex->alloc(tinyInfo[6]+1,1);
3285       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3286       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3287       myConnec->alloc(tinyInfo[7],1);
3288       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3289       setConnectivity(myConnec, myConnecIndex);
3290     }
3291 }
3292
3293 /*!
3294  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3295  * CellIds are given using range specified by a start an end and step.
3296  */
3297 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3298 {
3299   checkFullyDefined();
3300   int ncell=getNumberOfCells();
3301   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3302   ret->_mesh_dim=_mesh_dim;
3303   ret->setCoords(_coords);
3304   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3306   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3307   int work=start;
3308   const int *conn=_nodal_connec->getConstPointer();
3309   const int *connIndex=_nodal_connec_index->getConstPointer();
3310   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3311     {
3312       if(work>=0 && work<ncell)
3313         {
3314           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3315         }
3316       else
3317         {
3318           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3319           throw INTERP_KERNEL::Exception(oss.str().c_str());
3320         }
3321     }
3322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3323   int *newConnPtr=newConn->getPointer();
3324   std::set<INTERP_KERNEL::NormalizedCellType> types;
3325   work=start;
3326   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3327     {
3328       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3329       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3330     }
3331   ret->setConnectivity(newConn,newConnI,false);
3332   ret->_types=types;
3333   ret->copyTinyInfoFrom(this);
3334   return ret.retn();
3335 }
3336
3337 /*!
3338  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3339  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3340  * The return newly allocated mesh will share the same coordinates as \a this.
3341  */
3342 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3343 {
3344   checkConnectivityFullyDefined();
3345   int ncell=getNumberOfCells();
3346   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3347   ret->_mesh_dim=_mesh_dim;
3348   ret->setCoords(_coords);
3349   std::size_t nbOfElemsRet=std::distance(begin,end);
3350   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3351   connIndexRet[0]=0;
3352   const int *conn=_nodal_connec->getConstPointer();
3353   const int *connIndex=_nodal_connec_index->getConstPointer();
3354   int newNbring=0;
3355   for(const int *work=begin;work!=end;work++,newNbring++)
3356     {
3357       if(*work>=0 && *work<ncell)
3358         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3359       else
3360         {
3361           free(connIndexRet);
3362           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3363           throw INTERP_KERNEL::Exception(oss.str().c_str());
3364         }
3365     }
3366   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3367   int *connRetWork=connRet;
3368   std::set<INTERP_KERNEL::NormalizedCellType> types;
3369   for(const int *work=begin;work!=end;work++)
3370     {
3371       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3372       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3373     }
3374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3375   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3377   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3378   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3379   ret->_types=types;
3380   ret->copyTinyInfoFrom(this);
3381   return ret.retn();
3382 }
3383
3384 /*!
3385  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3386  * mesh.<br>
3387  * For 1D cells, the returned field contains lengths.<br>
3388  * For 2D cells, the returned field contains areas.<br>
3389  * For 3D cells, the returned field contains volumes.
3390  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3391  *         orientation, i.e. the volume is always positive.
3392  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3393  *         and one time . The caller is to delete this field using decrRef() as it is no
3394  *         more needed.
3395  */
3396 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3397 {
3398   std::string name="MeasureOfMesh_";
3399   name+=getName();
3400   int nbelem=getNumberOfCells();
3401   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3402   field->setName(name);
3403   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3404   array->alloc(nbelem,1);
3405   double *area_vol=array->getPointer();
3406   field->setArray(array) ; array=0;
3407   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3408   field->synchronizeTimeWithMesh();
3409   if(getMeshDimension()!=-1)
3410     {
3411       int ipt;
3412       INTERP_KERNEL::NormalizedCellType type;
3413       int dim_space=getSpaceDimension();
3414       const double *coords=getCoords()->getConstPointer();
3415       const int *connec=getNodalConnectivity()->getConstPointer();
3416       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3417       for(int iel=0;iel<nbelem;iel++)
3418         {
3419           ipt=connec_index[iel];
3420           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3421           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);
3422         }
3423       if(isAbs)
3424         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3425     }
3426   else
3427     {
3428       area_vol[0]=std::numeric_limits<double>::max();
3429     }
3430   return field.retn();
3431 }
3432
3433 /*!
3434  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3435  * mesh.<br>
3436  * For 1D cells, the returned array contains lengths.<br>
3437  * For 2D cells, the returned array contains areas.<br>
3438  * For 3D cells, the returned array contains volumes.
3439  * This method avoids building explicitly a part of \a this mesh to perform the work.
3440  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3441  *         orientation, i.e. the volume is always positive.
3442  *  \param [in] begin - an array of cell ids of interest.
3443  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3444  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3445  *          delete this array using decrRef() as it is no more needed.
3446  * 
3447  *  \if ENABLE_EXAMPLES
3448  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3449  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3450  *  \endif
3451  *  \sa getMeasureField()
3452  */
3453 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3454 {
3455   std::string name="PartMeasureOfMesh_";
3456   name+=getName();
3457   int nbelem=(int)std::distance(begin,end);
3458   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3459   array->setName(name);
3460   array->alloc(nbelem,1);
3461   double *area_vol=array->getPointer();
3462   if(getMeshDimension()!=-1)
3463     {
3464       int ipt;
3465       INTERP_KERNEL::NormalizedCellType type;
3466       int dim_space=getSpaceDimension();
3467       const double *coords=getCoords()->getConstPointer();
3468       const int *connec=getNodalConnectivity()->getConstPointer();
3469       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3470       for(const int *iel=begin;iel!=end;iel++)
3471         {
3472           ipt=connec_index[*iel];
3473           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3474           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3475         }
3476       if(isAbs)
3477         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3478     }
3479   else
3480     {
3481       area_vol[0]=std::numeric_limits<double>::max();
3482     }
3483   return array.retn();
3484 }
3485
3486 /*!
3487  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3488  * \a this one. The returned field contains the dual cell volume for each corresponding
3489  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3490  *  the dual mesh in P1 sens of \a this.<br>
3491  * For 1D cells, the returned field contains lengths.<br>
3492  * For 2D cells, the returned field contains areas.<br>
3493  * For 3D cells, the returned field contains volumes.
3494  * This method is useful to check "P1*" conservative interpolators.
3495  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3496  *         orientation, i.e. the volume is always positive.
3497  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3498  *          nodes and one time. The caller is to delete this array using decrRef() as
3499  *          it is no more needed.
3500  */
3501 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3502 {
3503   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3504   std::string name="MeasureOnNodeOfMesh_";
3505   name+=getName();
3506   int nbNodes=getNumberOfNodes();
3507   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3508   double cst=1./((double)getMeshDimension()+1.);
3509   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3510   array->alloc(nbNodes,1);
3511   double *valsToFill=array->getPointer();
3512   std::fill(valsToFill,valsToFill+nbNodes,0.);
3513   const double *values=tmp->getArray()->getConstPointer();
3514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3515   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3516   getReverseNodalConnectivity(da,daInd);
3517   const int *daPtr=da->getConstPointer();
3518   const int *daIPtr=daInd->getConstPointer();
3519   for(int i=0;i<nbNodes;i++)
3520     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3521       valsToFill[i]+=cst*values[*cell];
3522   ret->setMesh(this);
3523   ret->setArray(array);
3524   return ret.retn();
3525 }
3526
3527 /*!
3528  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3529  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3530  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3531  * and are normalized.
3532  * <br> \a this can be either 
3533  * - a  2D mesh in 2D or 3D space or 
3534  * - an 1D mesh in 2D space.
3535  * 
3536  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3537  *          cells and one time. The caller is to delete this field using decrRef() as
3538  *          it is no more needed.
3539  *  \throw If the nodal connectivity of cells is not defined.
3540  *  \throw If the coordinates array is not set.
3541  *  \throw If the mesh dimension is not set.
3542  *  \throw If the mesh and space dimension is not as specified above.
3543  */
3544 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3545 {
3546   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3547     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3548   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3549   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3550   int nbOfCells=getNumberOfCells();
3551   int nbComp=getMeshDimension()+1;
3552   array->alloc(nbOfCells,nbComp);
3553   double *vals=array->getPointer();
3554   const int *connI=_nodal_connec_index->getConstPointer();
3555   const int *conn=_nodal_connec->getConstPointer();
3556   const double *coords=_coords->getConstPointer();
3557   if(getMeshDimension()==2)
3558     {
3559       if(getSpaceDimension()==3)
3560         {
3561           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3562           const double *locPtr=loc->getConstPointer();
3563           for(int i=0;i<nbOfCells;i++,vals+=3)
3564             {
3565               int offset=connI[i];
3566               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3567               double n=INTERP_KERNEL::norm<3>(vals);
3568               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3569             }
3570         }
3571       else
3572         {
3573           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3574           const double *isAbsPtr=isAbs->getArray()->begin();
3575           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3576             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3577         }
3578     }
3579   else//meshdimension==1
3580     {
3581       double tmp[2];
3582       for(int i=0;i<nbOfCells;i++)
3583         {
3584           int offset=connI[i];
3585           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3586           double n=INTERP_KERNEL::norm<2>(tmp);
3587           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3588           *vals++=-tmp[1];
3589           *vals++=tmp[0];
3590         }
3591     }
3592   ret->setArray(array);
3593   ret->setMesh(this);
3594   ret->synchronizeTimeWithSupport();
3595   return ret.retn();
3596 }
3597
3598 /*!
3599  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3600  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3601  * and are normalized.
3602  * <br> \a this can be either 
3603  * - a  2D mesh in 2D or 3D space or 
3604  * - an 1D mesh in 2D space.
3605  * 
3606  * This method avoids building explicitly a part of \a this mesh to perform the work.
3607  *  \param [in] begin - an array of cell ids of interest.
3608  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3609  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3610  *          cells and one time. The caller is to delete this field using decrRef() as
3611  *          it is no more needed.
3612  *  \throw If the nodal connectivity of cells is not defined.
3613  *  \throw If the coordinates array is not set.
3614  *  \throw If the mesh dimension is not set.
3615  *  \throw If the mesh and space dimension is not as specified above.
3616  *  \sa buildOrthogonalField()
3617  *
3618  *  \if ENABLE_EXAMPLES
3619  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3620  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3621  *  \endif
3622  */
3623 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3624 {
3625   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3626     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3627   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3628   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3629   std::size_t nbelems=std::distance(begin,end);
3630   int nbComp=getMeshDimension()+1;
3631   array->alloc((int)nbelems,nbComp);
3632   double *vals=array->getPointer();
3633   const int *connI=_nodal_connec_index->getConstPointer();
3634   const int *conn=_nodal_connec->getConstPointer();
3635   const double *coords=_coords->getConstPointer();
3636   if(getMeshDimension()==2)
3637     {
3638       if(getSpaceDimension()==3)
3639         {
3640           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3641           const double *locPtr=loc->getConstPointer();
3642           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3643             {
3644               int offset=connI[*i];
3645               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3646               double n=INTERP_KERNEL::norm<3>(vals);
3647               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3648             }
3649         }
3650       else
3651         {
3652           for(std::size_t i=0;i<nbelems;i++)
3653             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3654         }
3655     }
3656   else//meshdimension==1
3657     {
3658       double tmp[2];
3659       for(const int *i=begin;i!=end;i++)
3660         {
3661           int offset=connI[*i];
3662           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3663           double n=INTERP_KERNEL::norm<2>(tmp);
3664           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3665           *vals++=-tmp[1];
3666           *vals++=tmp[0];
3667         }
3668     }
3669   ret->setArray(array);
3670   ret->setMesh(this);
3671   ret->synchronizeTimeWithSupport();
3672   return ret.retn();
3673 }
3674
3675 /*!
3676  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3677  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3678  * and are \b not normalized.
3679  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3680  *          cells and one time. The caller is to delete this field using decrRef() as
3681  *          it is no more needed.
3682  *  \throw If the nodal connectivity of cells is not defined.
3683  *  \throw If the coordinates array is not set.
3684  *  \throw If \a this->getMeshDimension() != 1.
3685  *  \throw If \a this mesh includes cells of type other than SEG2.
3686  */
3687 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3688 {
3689   if(getMeshDimension()!=1)
3690     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3691   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3692     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3693   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3694   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3695   int nbOfCells=getNumberOfCells();
3696   int spaceDim=getSpaceDimension();
3697   array->alloc(nbOfCells,spaceDim);
3698   double *pt=array->getPointer();
3699   const double *coo=getCoords()->getConstPointer();
3700   std::vector<int> conn;
3701   conn.reserve(2);
3702   for(int i=0;i<nbOfCells;i++)
3703     {
3704       conn.resize(0);
3705       getNodeIdsOfCell(i,conn);
3706       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3707     }
3708   ret->setArray(array);
3709   ret->setMesh(this);
3710   ret->synchronizeTimeWithSupport();
3711   return ret.retn();
3712 }
3713
3714 /*!
3715  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3716  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3717  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3718  * from. If a result face is shared by two 3D cells, then the face in included twice in
3719  * the result mesh.
3720  *  \param [in] origin - 3 components of a point defining location of the plane.
3721  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3722  *         must be greater than 1e-6.
3723  *  \param [in] eps - half-thickness of the plane.
3724  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3725  *         producing correspondent 2D cells. The caller is to delete this array
3726  *         using decrRef() as it is no more needed.
3727  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3728  *         not share the node coordinates array with \a this mesh. The caller is to
3729  *         delete this mesh using decrRef() as it is no more needed.  
3730  *  \throw If the coordinates array is not set.
3731  *  \throw If the nodal connectivity of cells is not defined.
3732  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3733  *  \throw If magnitude of \a vec is less than 1e-6.
3734  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3735  *  \throw If \a this includes quadratic cells.
3736  */
3737 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3738 {
3739   checkFullyDefined();
3740   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3742   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3743   if(candidates->empty())
3744     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3745   std::vector<int> nodes;
3746   DataArrayInt *cellIds1D=0;
3747   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3748   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3749   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3750   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3752   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3753   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3754   revDesc2=0; revDescIndx2=0;
3755   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3756   revDesc1=0; revDescIndx1=0;
3757   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3758   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3759   //
3760   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3761   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3762     cut3DCurve[*it]=-1;
3763   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3764   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3765   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3766                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3767                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3768   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3769   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3770   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3771   if(cellIds2->empty())
3772     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3773   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3774   ret->setCoords(mDesc1->getCoords());
3775   ret->setConnectivity(conn,connI,true);
3776   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3777   return ret.retn();
3778 }
3779
3780 /*!
3781  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3782 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
3783 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3784 the result mesh.
3785  *  \param [in] origin - 3 components of a point defining location of the plane.
3786  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3787  *         must be greater than 1e-6.
3788  *  \param [in] eps - half-thickness of the plane.
3789  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3790  *         producing correspondent segments. The caller is to delete this array
3791  *         using decrRef() as it is no more needed.
3792  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3793  *         mesh in 3D space. This mesh does not share the node coordinates array with
3794  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3795  *         no more needed. 
3796  *  \throw If the coordinates array is not set.
3797  *  \throw If the nodal connectivity of cells is not defined.
3798  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3799  *  \throw If magnitude of \a vec is less than 1e-6.
3800  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3801  *  \throw If \a this includes quadratic cells.
3802  */
3803 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3804 {
3805   checkFullyDefined();
3806   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3807     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3809   if(candidates->empty())
3810     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3811   std::vector<int> nodes;
3812   DataArrayInt *cellIds1D=0;
3813   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3814   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3815   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3816   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3817   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3818   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3819   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3820   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3822   //
3823   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3824   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3825     cut3DCurve[*it]=-1;
3826   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3827   int ncellsSub=subMesh->getNumberOfCells();
3828   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3829   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3830                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3831                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3832   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3833   conn->alloc(0,1);
3834   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3835   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3836   for(int i=0;i<ncellsSub;i++)
3837     {
3838       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3839         {
3840           if(cut3DSurf[i].first!=-2)
3841             {
3842               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3843               connI->pushBackSilent(conn->getNumberOfTuples());
3844               cellIds2->pushBackSilent(i);
3845             }
3846           else
3847             {
3848               int cellId3DSurf=cut3DSurf[i].second;
3849               int offset=nodalI[cellId3DSurf]+1;
3850               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3851               for(int j=0;j<nbOfEdges;j++)
3852                 {
3853                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3854                   connI->pushBackSilent(conn->getNumberOfTuples());
3855                   cellIds2->pushBackSilent(cellId3DSurf);
3856                 }
3857             }
3858         }
3859     }
3860   if(cellIds2->empty())
3861     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3862   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3863   ret->setCoords(mDesc1->getCoords());
3864   ret->setConnectivity(conn,connI,true);
3865   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3866   return ret.retn();
3867 }
3868
3869 /*!
3870  * Finds cells whose bounding boxes intersect a given plane.
3871  *  \param [in] origin - 3 components of a point defining location of the plane.
3872  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3873  *         must be greater than 1e-6.
3874  *  \param [in] eps - half-thickness of the plane.
3875  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3876  *         cells. The caller is to delete this array using decrRef() as it is no more
3877  *         needed.
3878  *  \throw If the coordinates array is not set.
3879  *  \throw If the nodal connectivity of cells is not defined.
3880  *  \throw If \a this->getSpaceDimension() != 3.
3881  *  \throw If magnitude of \a vec is less than 1e-6.
3882  *  \sa buildSlice3D()
3883  */
3884 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3885 {
3886   checkFullyDefined();
3887   if(getSpaceDimension()!=3)
3888     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3889   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3890   if(normm<1e-6)
3891     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3892   double vec2[3];
3893   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3894   double angle=acos(vec[2]/normm);
3895   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3896   double bbox[6];
3897   if(angle>eps)
3898     {
3899       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3900       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3901       if(normm2/normm>1e-6)
3902         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3903       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3904       mw->setCoords(coo);
3905       mw->getBoundingBox(bbox);
3906       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3907       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3908     }
3909   else
3910     {
3911       getBoundingBox(bbox);
3912       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3913       cellIds=getCellsInBoundingBox(bbox,eps);
3914     }
3915   return cellIds.retn();
3916 }
3917
3918 /*!
3919  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3920  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3921  * No consideration of coordinate is done by this method.
3922  * 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)
3923  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3924  */
3925 bool MEDCouplingUMesh::isContiguous1D() const
3926 {
3927   if(getMeshDimension()!=1)
3928     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3929   int nbCells=getNumberOfCells();
3930   if(nbCells<1)
3931     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3932   const int *connI=_nodal_connec_index->getConstPointer();
3933   const int *conn=_nodal_connec->getConstPointer();
3934   int ref=conn[connI[0]+2];
3935   for(int i=1;i<nbCells;i++)
3936     {
3937       if(conn[connI[i]+1]!=ref)
3938         return false;
3939       ref=conn[connI[i]+2];
3940     }
3941   return true;
3942 }
3943
3944 /*!
3945  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3946  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3947  * \param pt reference point of the line
3948  * \param v normalized director vector of the line
3949  * \param eps max precision before throwing an exception
3950  * \param res output of size this->getNumberOfCells
3951  */
3952 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3953 {
3954   if(getMeshDimension()!=1)
3955     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3956   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3957     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3958   if(getSpaceDimension()!=3)
3959     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3960   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3961   const double *fPtr=f->getArray()->getConstPointer();
3962   double tmp[3];
3963   for(int i=0;i<getNumberOfCells();i++)
3964     {
3965       const double *tmp1=fPtr+3*i;
3966       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3967       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3968       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3969       double n1=INTERP_KERNEL::norm<3>(tmp);
3970       n1/=INTERP_KERNEL::norm<3>(tmp1);
3971       if(n1>eps)
3972         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3973     }
3974   const double *coo=getCoords()->getConstPointer();
3975   for(int i=0;i<getNumberOfNodes();i++)
3976     {
3977       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3978       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3979       res[i]=std::accumulate(tmp,tmp+3,0.);
3980     }
3981 }
3982
3983 /*!
3984  * 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. 
3985  * \a this is expected to be a mesh so that its space dimension is equal to its
3986  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3987  * 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).
3988  *
3989  * 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
3990  * 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).
3991  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3992  *
3993  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3994  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3995  *
3996  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3997  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3998  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3999  * \return the positive value of the distance.
4000  * \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
4001  * dimension - 1.
4002  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4003  */
4004 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4005 {
4006   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4007   if(meshDim!=spaceDim-1)
4008     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4009   if(meshDim!=2 && meshDim!=1)
4010     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4011   checkFullyDefined();
4012   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4013     { 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()); }
4014   DataArrayInt *ret1=0;
4015   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4016   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4017   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4018   cellId=*ret1Safe->begin();
4019   return *ret0->begin();
4020 }
4021
4022 /*!
4023  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4024  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4025  * 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
4026  * 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).
4027  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4028  * 
4029  * \a this is expected to be a mesh so that its space dimension is equal to its
4030  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4031  * 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).
4032  *
4033  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4034  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4035  *
4036  * \param [in] pts the list of points in which each tuple represents a point
4037  * \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.
4038  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4039  * \throw if number of components of \a pts is not equal to the space dimension.
4040  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4041  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4042  */
4043 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4044 {
4045   if(!pts)
4046     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4047   pts->checkAllocated();
4048   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4049   if(meshDim!=spaceDim-1)
4050     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4051   if(meshDim!=2 && meshDim!=1)
4052     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4053   if(pts->getNumberOfComponents()!=spaceDim)
4054     {
4055       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4056       throw INTERP_KERNEL::Exception(oss.str().c_str());
4057     }
4058   checkFullyDefined();
4059   int nbCells=getNumberOfCells();
4060   if(nbCells==0)
4061     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4062   int nbOfPts=pts->getNumberOfTuples();
4063   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4064   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4065   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4066   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4067   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4068   const double *bbox(bboxArr->begin());
4069   switch(spaceDim)
4070   {
4071     case 3:
4072       {
4073         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4074         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4075           {
4076             double x=std::numeric_limits<double>::max();
4077             std::vector<int> elems;
4078             myTree.getMinDistanceOfMax(ptsPtr,x);
4079             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4080             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4081           }
4082         break;
4083       }
4084     case 2:
4085       {
4086         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4087         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4088           {
4089             double x=std::numeric_limits<double>::max();
4090             std::vector<int> elems;
4091             myTree.getMinDistanceOfMax(ptsPtr,x);
4092             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4093             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4094           }
4095         break;
4096       }
4097     default:
4098       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4099   }
4100   cellIds=ret1.retn();
4101   return ret0.retn();
4102 }
4103
4104 /*!
4105  * \param [in] pt the start pointer (included) of the coordinates of the point
4106  * \param [in] cellIdsBg the start pointer (included) of cellIds
4107  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4108  * \param [in] nc nodal connectivity
4109  * \param [in] ncI nodal connectivity index
4110  * \param [in,out] ret0 the min distance between \a this and the external input point
4111  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4112  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4113  */
4114 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)
4115 {
4116   cellId=-1;
4117   ret0=std::numeric_limits<double>::max();
4118   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4119     {
4120       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4121       {
4122         case INTERP_KERNEL::NORM_TRI3:
4123           {
4124             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4125             if(tmp<ret0)
4126               { ret0=tmp; cellId=*zeCell; }
4127             break;
4128           }
4129         case INTERP_KERNEL::NORM_QUAD4:
4130         case INTERP_KERNEL::NORM_POLYGON:
4131           {
4132             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4133             if(tmp<ret0)
4134               { ret0=tmp; cellId=*zeCell; }
4135             break;
4136           }
4137         default:
4138           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4139       }
4140     }
4141 }
4142
4143 /*!
4144  * \param [in] pt the start pointer (included) of the coordinates of the point
4145  * \param [in] cellIdsBg the start pointer (included) of cellIds
4146  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4147  * \param [in] nc nodal connectivity
4148  * \param [in] ncI nodal connectivity index
4149  * \param [in,out] ret0 the min distance between \a this and the external input point
4150  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4151  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4152  */
4153 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)
4154 {
4155   cellId=-1;
4156   ret0=std::numeric_limits<double>::max();
4157   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4158     {
4159       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4160       {
4161         case INTERP_KERNEL::NORM_SEG2:
4162           {
4163             std::size_t uselessEntry=0;
4164             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4165             tmp=sqrt(tmp);
4166             if(tmp<ret0)
4167               { ret0=tmp; cellId=*zeCell; }
4168             break;
4169           }
4170         default:
4171           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4172       }
4173     }
4174 }
4175
4176 /*!
4177  * Finds cells in contact with a ball (i.e. a point with precision). 
4178  * 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.
4179  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4180  *
4181  * \warning This method is suitable if the caller intends to evaluate only one
4182  *          point, for more points getCellsContainingPoints() is recommended as it is
4183  *          faster. 
4184  *  \param [in] pos - array of coordinates of the ball central point.
4185  *  \param [in] eps - ball radius.
4186  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4187  *         if there are no such cells.
4188  *  \throw If the coordinates array is not set.
4189  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4190  */
4191 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4192 {
4193   std::vector<int> elts;
4194   getCellsContainingPoint(pos,eps,elts);
4195   if(elts.empty())
4196     return -1;
4197   return elts.front();
4198 }
4199
4200 /*!
4201  * Finds cells in contact with a ball (i.e. a point with precision).
4202  * 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.
4203  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4204  * \warning This method is suitable if the caller intends to evaluate only one
4205  *          point, for more points getCellsContainingPoints() is recommended as it is
4206  *          faster. 
4207  *  \param [in] pos - array of coordinates of the ball central point.
4208  *  \param [in] eps - ball radius.
4209  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4210  *         before inserting ids.
4211  *  \throw If the coordinates array is not set.
4212  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4213  *
4214  *  \if ENABLE_EXAMPLES
4215  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4216  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4217  *  \endif
4218  */
4219 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4220 {
4221   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4222   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4223   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4224 }
4225
4226 /// @cond INTERNAL
4227
4228 namespace ParaMEDMEM
4229 {
4230   template<const int SPACEDIMM>
4231   class DummyClsMCUG
4232   {
4233   public:
4234     static const int MY_SPACEDIM=SPACEDIMM;
4235     static const int MY_MESHDIM=8;
4236     typedef int MyConnType;
4237     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4238     // begin
4239     // useless, but for windows compilation ...
4240     const double* getCoordinatesPtr() const { return 0; }
4241     const int* getConnectivityPtr() const { return 0; }
4242     const int* getConnectivityIndexPtr() const { return 0; }
4243     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4244     // end
4245   };
4246
4247   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4248   {
4249     INTERP_KERNEL::Edge *ret(0);
4250     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]));
4251     m[n0]=bg[0]; m[n1]=bg[1];
4252     switch(typ)
4253     {
4254       case INTERP_KERNEL::NORM_SEG2:
4255         {
4256           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4257           break;
4258         }
4259       case INTERP_KERNEL::NORM_SEG3:
4260         {
4261           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4262           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4263           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4264           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4265           bool colinearity(inters.areColinears());
4266           delete e1; delete e2;
4267           if(colinearity)
4268             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4269           else
4270             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4271           break;
4272         }
4273       default:
4274         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4275     }
4276     return ret;
4277   }
4278
4279   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4280   {
4281     INTERP_KERNEL::Edge *ret=0;
4282     switch(typ)
4283     {
4284       case INTERP_KERNEL::NORM_SEG2:
4285         {
4286           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4287           break;
4288         }
4289       case INTERP_KERNEL::NORM_SEG3:
4290         {
4291           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4292           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4293           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4294           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4295           bool colinearity=inters.areColinears();
4296           delete e1; delete e2;
4297           if(colinearity)
4298             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4299           else
4300             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4301           mapp2[bg[2]].second=false;
4302           break;
4303         }
4304       default:
4305         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4306     }
4307     return ret;
4308   }
4309
4310   /*!
4311    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4312    * the global mesh 'mDesc'.
4313    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4314    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4315    */
4316   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4317                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4318   {
4319     mapp.clear();
4320     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.
4321     const double *coo=mDesc->getCoords()->getConstPointer();
4322     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4323     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4324     std::set<int> s;
4325     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4326       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4327     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4328       {
4329         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4330         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4331       }
4332     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4333     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4334       {
4335         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4336         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4337       }
4338     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4339       {
4340         if((*it2).second.second)
4341           mapp[(*it2).second.first]=(*it2).first;
4342         ((*it2).second.first)->decrRef();
4343       }
4344     return ret;
4345   }
4346
4347   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4348   {
4349     if(nodeId>=offset2)
4350       {
4351         int locId=nodeId-offset2;
4352         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4353       }
4354     if(nodeId>=offset1)
4355       {
4356         int locId=nodeId-offset1;
4357         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4358       }
4359     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4360   }
4361
4362   /**
4363    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4364    */
4365   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4366                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4367                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4368   {
4369     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4370       {
4371         int eltId1=abs(*desc1)-1;
4372         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4373           {
4374             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4375             if(it==mappRev.end())
4376               {
4377                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4378                 mapp[node]=*it1;
4379                 mappRev[*it1]=node;
4380               }
4381           }
4382       }
4383   }
4384 }
4385
4386 /// @endcond
4387
4388 template<int SPACEDIM>
4389 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4390                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4391 {
4392   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4393   int *eltsIndexPtr(eltsIndex->getPointer());
4394   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4395   const double *bbox(bboxArr->begin());
4396   int nbOfCells=getNumberOfCells();
4397   const int *conn=_nodal_connec->getConstPointer();
4398   const int *connI=_nodal_connec_index->getConstPointer();
4399   double bb[2*SPACEDIM];
4400   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4401   for(int i=0;i<nbOfPoints;i++)
4402     {
4403       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4404       for(int j=0;j<SPACEDIM;j++)
4405         {
4406           bb[2*j]=pos[SPACEDIM*i+j];
4407           bb[2*j+1]=pos[SPACEDIM*i+j];
4408         }
4409       std::vector<int> candidates;
4410       myTree.getIntersectingElems(bb,candidates);
4411       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4412         {
4413           int sz(connI[(*iter)+1]-connI[*iter]-1);
4414           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4415           bool status(false);
4416           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4417             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4418           else
4419             {
4420               if(SPACEDIM!=2)
4421                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4422               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4423               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4424               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4425               INTERP_KERNEL::QuadraticPolygon *pol(0);
4426               for(int j=0;j<sz;j++)
4427                 {
4428                   int nodeId(conn[connI[*iter]+1+j]);
4429                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4430                 }
4431               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4432                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4433               else
4434                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4435               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4436               double a(0.),b(0.),c(0.);
4437               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4438               status=pol->isInOrOut2(n);
4439               delete pol; n->decrRef();
4440             }
4441           if(status)
4442             {
4443               eltsIndexPtr[i+1]++;
4444               elts->pushBackSilent(*iter);
4445             }
4446         }
4447     }
4448 }
4449 /*!
4450  * Finds cells in contact with several balls (i.e. points with precision).
4451  * This method is an extension of getCellContainingPoint() and
4452  * getCellsContainingPoint() for the case of multiple points.
4453  * 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.
4454  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4455  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4456  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4457  *         this->getSpaceDimension() * \a nbOfPoints 
4458  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4459  *  \param [in] eps - radius of balls (i.e. the precision).
4460  *  \param [out] elts - vector returning ids of found cells.
4461  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4462  *         dividing cell ids in \a elts into groups each referring to one
4463  *         point. Its every element (except the last one) is an index pointing to the
4464  *         first id of a group of cells. For example cells in contact with the *i*-th
4465  *         point are described by following range of indices:
4466  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4467  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4468  *         Number of cells in contact with the *i*-th point is
4469  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4470  *  \throw If the coordinates array is not set.
4471  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4472  *
4473  *  \if ENABLE_EXAMPLES
4474  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4475  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4476  *  \endif
4477  */
4478 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4479                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4480 {
4481   int spaceDim=getSpaceDimension();
4482   int mDim=getMeshDimension();
4483   if(spaceDim==3)
4484     {
4485       if(mDim==3)
4486         {
4487           const double *coords=_coords->getConstPointer();
4488           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4489         }
4490       /*else if(mDim==2)
4491         {
4492
4493         }*/
4494       else
4495         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4496     }
4497   else if(spaceDim==2)
4498     {
4499       if(mDim==2)
4500         {
4501           const double *coords=_coords->getConstPointer();
4502           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4503         }
4504       else
4505         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4506     }
4507   else if(spaceDim==1)
4508     {
4509       if(mDim==1)
4510         {
4511           const double *coords=_coords->getConstPointer();
4512           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4513         }
4514       else
4515         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4516     }
4517   else
4518     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4519 }
4520
4521 /*!
4522  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4523  * least two its edges intersect each other anywhere except their extremities. An
4524  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4525  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4526  *         cleared before filling in.
4527  *  \param [in] eps - precision.
4528  *  \throw If \a this->getMeshDimension() != 2.
4529  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4530  */
4531 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4532 {
4533   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4534   if(getMeshDimension()!=2)
4535     throw INTERP_KERNEL::Exception(msg);
4536   int spaceDim=getSpaceDimension();
4537   if(spaceDim!=2 && spaceDim!=3)
4538     throw INTERP_KERNEL::Exception(msg);
4539   const int *conn=_nodal_connec->getConstPointer();
4540   const int *connI=_nodal_connec_index->getConstPointer();
4541   int nbOfCells=getNumberOfCells();
4542   std::vector<double> cell2DinS2;
4543   for(int i=0;i<nbOfCells;i++)
4544     {
4545       int offset=connI[i];
4546       int nbOfNodesForCell=connI[i+1]-offset-1;
4547       if(nbOfNodesForCell<=3)
4548         continue;
4549       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4550       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4551       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4552         cells.push_back(i);
4553       cell2DinS2.clear();
4554     }
4555 }
4556
4557 /*!
4558  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4559  *
4560  * 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.
4561  * 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.
4562  * 
4563  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4564  * This convex envelop is computed using Jarvis march algorithm.
4565  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4566  * 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)
4567  * 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.
4568  *
4569  * \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.
4570  * \sa MEDCouplingUMesh::colinearize2D
4571  */
4572 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4573 {
4574   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4575     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4576   checkFullyDefined();
4577   const double *coords=getCoords()->getConstPointer();
4578   int nbOfCells=getNumberOfCells();
4579   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4580   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4581   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4582   int *workIndexOut=nodalConnecIndexOut->getPointer();
4583   *workIndexOut=0;
4584   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4585   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4586   std::set<INTERP_KERNEL::NormalizedCellType> types;
4587   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4588   isChanged->alloc(0,1);
4589   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4590     {
4591       int pos=nodalConnecOut->getNumberOfTuples();
4592       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4593         isChanged->pushBackSilent(i);
4594       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4595       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4596     }
4597   if(isChanged->empty())
4598     return 0;
4599   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4600   _types=types;
4601   return isChanged.retn();
4602 }
4603
4604 /*!
4605  * This method is \b NOT const because it can modify \a this.
4606  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4607  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4608  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4609  * \b 1 for translation and rotation around point of 'mesh1D'.
4610  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4611  */
4612 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4613 {
4614   checkFullyDefined();
4615   mesh1D->checkFullyDefined();
4616   if(!mesh1D->isContiguous1D())
4617     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4618   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4619     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4620   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4621     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4622   if(mesh1D->getMeshDimension()!=1)
4623     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4624   bool isQuad=false;
4625   if(isPresenceOfQuadratic())
4626     {
4627       if(mesh1D->isFullyQuadratic())
4628         isQuad=true;
4629       else
4630         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4631     }
4632   int oldNbOfNodes(getNumberOfNodes());
4633   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4634   switch(policy)
4635   {
4636     case 0:
4637       {
4638         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4639         break;
4640       }
4641     case 1:
4642       {
4643         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4644         break;
4645       }
4646     default:
4647       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4648   }
4649   setCoords(newCoords);
4650   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4651   updateTime();
4652   return ret.retn();
4653 }
4654
4655 /*!
4656  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4657  * If it is not the case an exception will be thrown.
4658  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4659  * intersection of plane defined by ('origin','vec').
4660  * This method has one in/out parameter : 'cut3DCurve'.
4661  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4662  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4663  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4664  * This method will throw an exception if \a this contains a non linear segment.
4665  */
4666 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4667 {
4668   checkFullyDefined();
4669   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4670     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4671   int ncells=getNumberOfCells();
4672   int nnodes=getNumberOfNodes();
4673   double vec2[3],vec3[3],vec4[3];
4674   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4675   if(normm<1e-6)
4676     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4677   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4678   const int *conn=_nodal_connec->getConstPointer();
4679   const int *connI=_nodal_connec_index->getConstPointer();
4680   const double *coo=_coords->getConstPointer();
4681   std::vector<double> addCoo;
4682   for(int i=0;i<ncells;i++)
4683     {
4684       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4685         {
4686           if(cut3DCurve[i]==-2)
4687             {
4688               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4689               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];
4690               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4691               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4692               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4693                 {
4694                   const double *st2=coo+3*st;
4695                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4696                   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]));
4697                   if(pos>eps && pos<1-eps)
4698                     {
4699                       int nNode=((int)addCoo.size())/3;
4700                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4701                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4702                       cut3DCurve[i]=nnodes+nNode;
4703                     }
4704                 }
4705             }
4706         }
4707       else
4708         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4709     }
4710   if(!addCoo.empty())
4711     {
4712       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4713       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4714       coo2->alloc(newNbOfNodes,3);
4715       double *tmp=coo2->getPointer();
4716       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4717       std::copy(addCoo.begin(),addCoo.end(),tmp);
4718       DataArrayDouble::SetArrayIn(coo2,_coords);
4719     }
4720 }
4721
4722 /*!
4723  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4724  * \param mesh1D is the input 1D mesh used for translation computation.
4725  * \return newCoords new coords filled by this method. 
4726  */
4727 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4728 {
4729   int oldNbOfNodes=getNumberOfNodes();
4730   int nbOf1DCells=mesh1D->getNumberOfCells();
4731   int spaceDim=getSpaceDimension();
4732   DataArrayDouble *ret=DataArrayDouble::New();
4733   std::vector<bool> isQuads;
4734   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4735   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4736   double *retPtr=ret->getPointer();
4737   const double *coords=getCoords()->getConstPointer();
4738   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4739   std::vector<int> v;
4740   std::vector<double> c;
4741   double vec[3];
4742   v.reserve(3);
4743   c.reserve(6);
4744   for(int i=0;i<nbOf1DCells;i++)
4745     {
4746       v.resize(0);
4747       mesh1D->getNodeIdsOfCell(i,v);
4748       c.resize(0);
4749       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4750       mesh1D->getCoordinatesOfNode(v[0],c);
4751       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4752       for(int j=0;j<oldNbOfNodes;j++)
4753         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4754       if(isQuad)
4755         {
4756           c.resize(0);
4757           mesh1D->getCoordinatesOfNode(v[1],c);
4758           mesh1D->getCoordinatesOfNode(v[0],c);
4759           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4760           for(int j=0;j<oldNbOfNodes;j++)
4761             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4762         }
4763     }
4764   ret->copyStringInfoFrom(*getCoords());
4765   return ret;
4766 }
4767
4768 /*!
4769  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4770  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4771  * \return newCoords new coords filled by this method. 
4772  */
4773 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4774 {
4775   if(mesh1D->getSpaceDimension()==2)
4776     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4777   if(mesh1D->getSpaceDimension()==3)
4778     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4779   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4780 }
4781
4782 /*!
4783  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4784  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4785  * \return newCoords new coords filled by this method. 
4786  */
4787 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4788 {
4789   if(isQuad)
4790     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4791   int oldNbOfNodes=getNumberOfNodes();
4792   int nbOf1DCells=mesh1D->getNumberOfCells();
4793   if(nbOf1DCells<2)
4794     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4795   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4796   int nbOfLevsInVec=nbOf1DCells+1;
4797   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4798   double *retPtr=ret->getPointer();
4799   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4800   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4801   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4802   tmp->setCoords(tmp2);
4803   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4804   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4805   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4806   for(int i=1;i<nbOfLevsInVec;i++)
4807     {
4808       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4809       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4810       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4811       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4812       tmp->translate(vec);
4813       double tmp3[2],radius,alpha,alpha0;
4814       const double *p0=i+1<nbOfLevsInVec?begin:third;
4815       const double *p1=i+1<nbOfLevsInVec?end:begin;
4816       const double *p2=i+1<nbOfLevsInVec?third:end;
4817       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4818       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]);
4819       double angle=acos(cosangle/(radius*radius));
4820       tmp->rotate(end,0,angle);
4821       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4822     }
4823   return ret.retn();
4824 }
4825
4826 /*!
4827  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4828  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4829  * \return newCoords new coords filled by this method. 
4830  */
4831 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4832 {
4833   if(isQuad)
4834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4835   int oldNbOfNodes=getNumberOfNodes();
4836   int nbOf1DCells=mesh1D->getNumberOfCells();
4837   if(nbOf1DCells<2)
4838     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4839   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4840   int nbOfLevsInVec=nbOf1DCells+1;
4841   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4842   double *retPtr=ret->getPointer();
4843   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4844   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4845   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4846   tmp->setCoords(tmp2);
4847   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4848   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4849   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4850   for(int i=1;i<nbOfLevsInVec;i++)
4851     {
4852       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4853       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4854       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4855       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4856       tmp->translate(vec);
4857       double tmp3[2],radius,alpha,alpha0;
4858       const double *p0=i+1<nbOfLevsInVec?begin:third;
4859       const double *p1=i+1<nbOfLevsInVec?end:begin;
4860       const double *p2=i+1<nbOfLevsInVec?third:end;
4861       double vecPlane[3]={
4862         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4863         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4864         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4865       };
4866       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4867       if(norm>1.e-7)
4868         {
4869           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4870           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4871           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4872           double s2=norm2;
4873           double c2=cos(asin(s2));
4874           double m[3][3]={
4875             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4876             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4877             {-vec2[1]*s2, vec2[0]*s2, c2}
4878           };
4879           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]};
4880           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]};
4881           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]};
4882           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4883           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]);
4884           double angle=acos(cosangle/(radius*radius));
4885           tmp->rotate(end,vecPlane,angle);
4886         }
4887       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4888     }
4889   return ret.retn();
4890 }
4891
4892 /*!
4893  * This method is private because not easy to use for end user. This method is const contrary to
4894  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4895  * the coords sorted slice by slice.
4896  * \param isQuad specifies presence of quadratic cells.
4897  */
4898 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4899 {
4900   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4901   int nbOf2DCells(getNumberOfCells());
4902   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4903   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4904   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4905   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4906   newConnI->alloc(nbOf3DCells+1,1);
4907   int *newConnIPtr(newConnI->getPointer());
4908   *newConnIPtr++=0;
4909   std::vector<int> newc;
4910   for(int j=0;j<nbOf2DCells;j++)
4911     {
4912       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4913       *newConnIPtr++=(int)newc.size();
4914     }
4915   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4916   int *newConnPtr(newConn->getPointer());
4917   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4918   newConnIPtr=newConnI->getPointer();
4919   for(int iz=0;iz<nbOf1DCells;iz++)
4920     {
4921       if(iz!=0)
4922         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4923       const int *posOfTypeOfCell(newConnIPtr);
4924       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4925         {
4926           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4927           if(icell!=*posOfTypeOfCell)
4928             {
4929               if(*iter!=-1)
4930                 *newConnPtr=(*iter)+iz*deltaPerLev;
4931               else
4932                 *newConnPtr=-1;
4933             }
4934           else
4935             {
4936               *newConnPtr=*iter;
4937               posOfTypeOfCell++;
4938             }
4939         }
4940     }
4941   ret->setConnectivity(newConn,newConnI,true);
4942   ret->setCoords(getCoords());
4943   return ret;
4944 }
4945
4946 /*!
4947  * Checks if \a this mesh is constituted by only quadratic cells.
4948  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4949  *  \throw If the coordinates array is not set.
4950  *  \throw If the nodal connectivity of cells is not defined.
4951  */
4952 bool MEDCouplingUMesh::isFullyQuadratic() const
4953 {
4954   checkFullyDefined();
4955   bool ret=true;
4956   int nbOfCells=getNumberOfCells();
4957   for(int i=0;i<nbOfCells && ret;i++)
4958     {
4959       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4960       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4961       ret=cm.isQuadratic();
4962     }
4963   return ret;
4964 }
4965
4966 /*!
4967  * Checks if \a this mesh includes any quadratic cell.
4968  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4969  *  \throw If the coordinates array is not set.
4970  *  \throw If the nodal connectivity of cells is not defined.
4971  */
4972 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4973 {
4974   checkFullyDefined();
4975   bool ret=false;
4976   int nbOfCells=getNumberOfCells();
4977   for(int i=0;i<nbOfCells && !ret;i++)
4978     {
4979       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4980       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4981       ret=cm.isQuadratic();
4982     }
4983   return ret;
4984 }
4985
4986 /*!
4987  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4988  * this mesh, it remains unchanged.
4989  *  \throw If the coordinates array is not set.
4990  *  \throw If the nodal connectivity of cells is not defined.
4991  */
4992 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4993 {
4994   checkFullyDefined();
4995   int nbOfCells=getNumberOfCells();
4996   int delta=0;
4997   const int *iciptr=_nodal_connec_index->getConstPointer();
4998   for(int i=0;i<nbOfCells;i++)
4999     {
5000       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5001       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5002       if(cm.isQuadratic())
5003         {
5004           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5005           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5006           if(!cml.isDynamic())
5007             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5008           else
5009             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5010         }
5011     }
5012   if(delta==0)
5013     return ;
5014   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5015   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5016   const int *icptr=_nodal_connec->getConstPointer();
5017   newConn->alloc(getMeshLength()-delta,1);
5018   newConnI->alloc(nbOfCells+1,1);
5019   int *ocptr=newConn->getPointer();
5020   int *ociptr=newConnI->getPointer();
5021   *ociptr=0;
5022   _types.clear();
5023   for(int i=0;i<nbOfCells;i++,ociptr++)
5024     {
5025       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5026       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5027       if(!cm.isQuadratic())
5028         {
5029           _types.insert(type);
5030           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5031           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5032         }
5033       else
5034         {
5035           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5036           _types.insert(typel);
5037           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5038           int newNbOfNodes=cml.getNumberOfNodes();
5039           if(cml.isDynamic())
5040             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5041           *ocptr++=(int)typel;
5042           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5043           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5044         }
5045     }
5046   setConnectivity(newConn,newConnI,false);
5047 }
5048
5049 /*!
5050  * This method converts all linear cell in \a this to quadratic one.
5051  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5052  * 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)
5053  * 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.
5054  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5055  * end of the existing coordinates.
5056  * 
5057  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5058  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5059  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5060  * 
5061  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5062  *
5063  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5064  */
5065 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5066 {
5067   DataArrayInt *conn=0,*connI=0;
5068   DataArrayDouble *coords=0;
5069   std::set<INTERP_KERNEL::NormalizedCellType> types;
5070   checkFullyDefined();
5071   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5072   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5073   int meshDim=getMeshDimension();
5074   switch(conversionType)
5075   {
5076     case 0:
5077       switch(meshDim)
5078       {
5079         case 1:
5080           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5081           connSafe=conn; connISafe=connI; coordsSafe=coords;
5082           break;
5083         case 2:
5084           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5085           connSafe=conn; connISafe=connI; coordsSafe=coords;
5086           break;
5087         case 3:
5088           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5089           connSafe=conn; connISafe=connI; coordsSafe=coords;
5090           break;
5091         default:
5092           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5093       }
5094       break;
5095         case 1:
5096           {
5097             switch(meshDim)
5098             {
5099               case 1:
5100                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5101                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5102                 break;
5103               case 2:
5104                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5105                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5106                 break;
5107               case 3:
5108                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5109                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5110                 break;
5111               default:
5112                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5113             }
5114             break;
5115           }
5116         default:
5117           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5118   }
5119   setConnectivity(connSafe,connISafe,false);
5120   _types=types;
5121   setCoords(coordsSafe);
5122   return ret.retn();
5123 }
5124
5125 #if 0
5126 /*!
5127  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5128  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5129  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5130  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5131  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5132  * This method can be seen as the opposite method of colinearize2D.
5133  * 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
5134  * to avoid to modify the numbering of existing nodes.
5135  *
5136  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5137  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5138  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5139  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5140  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5141  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5142  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5143  *
5144  * \sa buildDescendingConnectivity2
5145  */
5146 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5147                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5148 {
5149   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5150     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5151   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5152   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5153     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5154   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5155     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5156   //DataArrayInt *out0(0),*outi0(0);
5157   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5158   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5159   //out0s=out0s->buildUnique(); out0s->sort(true);
5160 }
5161 #endif
5162
5163 /*!
5164  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5165  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5166  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5167  */
5168 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5169 {
5170   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5171   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5172   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5174   int nbOfCells=getNumberOfCells();
5175   int nbOfNodes=getNumberOfNodes();
5176   const int *cPtr=_nodal_connec->getConstPointer();
5177   const int *icPtr=_nodal_connec_index->getConstPointer();
5178   int lastVal=0,offset=nbOfNodes;
5179   for(int i=0;i<nbOfCells;i++,icPtr++)
5180     {
5181       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5182       if(type==INTERP_KERNEL::NORM_SEG2)
5183         {
5184           types.insert(INTERP_KERNEL::NORM_SEG3);
5185           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5186           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5187           newConn->pushBackSilent(offset++);
5188           lastVal+=4;
5189           newConnI->pushBackSilent(lastVal);
5190           ret->pushBackSilent(i);
5191         }
5192       else
5193         {
5194           types.insert(type);
5195           lastVal+=(icPtr[1]-icPtr[0]);
5196           newConnI->pushBackSilent(lastVal);
5197           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5198         }
5199     }
5200   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5201   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5202   return ret.retn();
5203 }
5204
5205 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
5206 {
5207   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5208   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5210   //
5211   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5212   DataArrayInt *conn1D=0,*conn1DI=0;
5213   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5214   DataArrayDouble *coordsTmp=0;
5215   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5216   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5217   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5218   const int *c1DPtr=conn1D->begin();
5219   const int *c1DIPtr=conn1DI->begin();
5220   int nbOfCells=getNumberOfCells();
5221   const int *cPtr=_nodal_connec->getConstPointer();
5222   const int *icPtr=_nodal_connec_index->getConstPointer();
5223   int lastVal=0;
5224   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5225     {
5226       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5227       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5228       if(!cm.isQuadratic())
5229         {
5230           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5231           types.insert(typ2); newConn->pushBackSilent(typ2);
5232           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5233           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5234             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5235           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5236           newConnI->pushBackSilent(lastVal);
5237           ret->pushBackSilent(i);
5238         }
5239       else
5240         {
5241           types.insert(typ);
5242           lastVal+=(icPtr[1]-icPtr[0]);
5243           newConnI->pushBackSilent(lastVal);
5244           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5245         }
5246     }
5247   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5248   return ret.retn();
5249 }
5250
5251 /*!
5252  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5253  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5254  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5255  */
5256 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5257 {
5258   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5259   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5260   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5261 }
5262
5263 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5264 {
5265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5266   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5267   //
5268   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5269   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5271   //
5272   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5273   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5274   DataArrayInt *conn1D=0,*conn1DI=0;
5275   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5276   DataArrayDouble *coordsTmp=0;
5277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5278   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5280   const int *c1DPtr=conn1D->begin();
5281   const int *c1DIPtr=conn1DI->begin();
5282   int nbOfCells=getNumberOfCells();
5283   const int *cPtr=_nodal_connec->getConstPointer();
5284   const int *icPtr=_nodal_connec_index->getConstPointer();
5285   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5286   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5287     {
5288       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5289       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5290       if(!cm.isQuadratic())
5291         {
5292           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5293           types.insert(typ2); newConn->pushBackSilent(typ2);
5294           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5295           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5296             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5297           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5298           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5299           newConnI->pushBackSilent(lastVal);
5300           ret->pushBackSilent(i);
5301         }
5302       else
5303         {
5304           types.insert(typ);
5305           lastVal+=(icPtr[1]-icPtr[0]);
5306           newConnI->pushBackSilent(lastVal);
5307           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5308         }
5309     }
5310   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5311   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5312   return ret.retn();
5313 }
5314
5315 /*!
5316  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5317  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5318  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5319  */
5320 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5321 {
5322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5323   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5324   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5325 }
5326
5327 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5328 {
5329   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5330   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5331   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5332   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5333   //
5334   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5337   //
5338   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5339   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5340   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5341   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5342   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5345   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5347   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5349   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5350   int nbOfCells=getNumberOfCells();
5351   const int *cPtr=_nodal_connec->getConstPointer();
5352   const int *icPtr=_nodal_connec_index->getConstPointer();
5353   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5354   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5355     {
5356       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5357       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5358       if(!cm.isQuadratic())
5359         {
5360           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5361           if(typ2==INTERP_KERNEL::NORM_ERROR)
5362             {
5363               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5364               throw INTERP_KERNEL::Exception(oss.str().c_str());
5365             }
5366           types.insert(typ2); newConn->pushBackSilent(typ2);
5367           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5368           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5369             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5370           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5371             {
5372               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5373               int tmpPos=newConn->getNumberOfTuples();
5374               newConn->pushBackSilent(nodeId2);
5375               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5376             }
5377           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5378           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5379           newConnI->pushBackSilent(lastVal);
5380           ret->pushBackSilent(i);
5381         }
5382       else
5383         {
5384           types.insert(typ);
5385           lastVal+=(icPtr[1]-icPtr[0]);
5386           newConnI->pushBackSilent(lastVal);
5387           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5388         }
5389     }
5390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5392   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5393   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5394   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5395   int *c=newConn->getPointer();
5396   const int *cI(newConnI->begin());
5397   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5398     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5399   offset=coordsTmp2Safe->getNumberOfTuples();
5400   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5401     c[cI[(*elt)+1]-1]+=offset;
5402   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5403   return ret.retn();
5404 }
5405
5406 /*!
5407  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5408  * so that the number of cells remains the same. Quadratic faces are converted to
5409  * polygons. This method works only for 2D meshes in
5410  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5411  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5412  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5413  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5414  *         a polylinized edge constituting the input polygon.
5415  *  \throw If the coordinates array is not set.
5416  *  \throw If the nodal connectivity of cells is not defined.
5417  *  \throw If \a this->getMeshDimension() != 2.
5418  *  \throw If \a this->getSpaceDimension() != 2.
5419  */
5420 void MEDCouplingUMesh::tessellate2D(double eps)
5421 {
5422   checkFullyDefined();
5423   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5424     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5425   double epsa=fabs(eps);
5426   if(epsa<std::numeric_limits<double>::min())
5427     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 !");
5428   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5429   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5430   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5432   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5433   revDesc1=0; revDescIndx1=0;
5434   mDesc->tessellate2DCurve(eps);
5435   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5436   setCoords(mDesc->getCoords());
5437 }
5438
5439 /*!
5440  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5441  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5442  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5443  *         a sub-divided edge.
5444  *  \throw If the coordinates array is not set.
5445  *  \throw If the nodal connectivity of cells is not defined.
5446  *  \throw If \a this->getMeshDimension() != 1.
5447  *  \throw If \a this->getSpaceDimension() != 2.
5448  */
5449 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5450 {
5451   checkFullyDefined();
5452   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5453     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5454   double epsa=fabs(eps);
5455   if(epsa<std::numeric_limits<double>::min())
5456     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 !");
5457   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5458   int nbCells=getNumberOfCells();
5459   int nbNodes=getNumberOfNodes();
5460   const int *conn=_nodal_connec->getConstPointer();
5461   const int *connI=_nodal_connec_index->getConstPointer();
5462   const double *coords=_coords->getConstPointer();
5463   std::vector<double> addCoo;
5464   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5466   newConnI->alloc(nbCells+1,1);
5467   int *newConnIPtr=newConnI->getPointer();
5468   *newConnIPtr=0;
5469   int tmp1[3];
5470   INTERP_KERNEL::Node *tmp2[3];
5471   std::set<INTERP_KERNEL::NormalizedCellType> types;
5472   for(int i=0;i<nbCells;i++,newConnIPtr++)
5473     {
5474       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5475       if(cm.isQuadratic())
5476         {//assert(connI[i+1]-connI[i]-1==3)
5477           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5478           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5479           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5480           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5481           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5482           if(eac)
5483             {
5484               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5485               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5486               delete eac;
5487               newConnIPtr[1]=(int)newConn.size();
5488             }
5489           else
5490             {
5491               types.insert(INTERP_KERNEL::NORM_SEG2);
5492               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5493               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5494               newConnIPtr[1]=newConnIPtr[0]+3;
5495             }
5496         }
5497       else
5498         {
5499           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5500           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5501           newConnIPtr[1]=newConnIPtr[0]+3;
5502         }
5503     }
5504   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5505     return ;
5506   _types=types;
5507   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5508   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5509   newConnArr->alloc((int)newConn.size(),1);
5510   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5511   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5512   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5513   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5514   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5515   std::copy(addCoo.begin(),addCoo.end(),work);
5516   DataArrayDouble::SetArrayIn(newCoords,_coords);
5517   updateTime();
5518 }
5519
5520 /*!
5521  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5522  * In addition, returns an array mapping new cells to old ones. <br>
5523  * This method typically increases the number of cells in \a this mesh
5524  * but the number of nodes remains \b unchanged.
5525  * That's why the 3D splitting policies
5526  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5527  *  \param [in] policy - specifies a pattern used for splitting.
5528  * The semantic of \a policy is:
5529  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5530  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5531  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5532  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5533  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5534  *          an id of old cell producing it. The caller is to delete this array using
5535  *         decrRef() as it is no more needed. 
5536  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5537  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5538  *          and \a this->getMeshDimension() != 3. 
5539  *  \throw If \a policy is not one of the four discussed above.
5540  *  \throw If the nodal connectivity of cells is not defined.
5541  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5542  */
5543 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5544 {
5545   switch(policy)
5546   {
5547     case 0:
5548       return simplexizePol0();
5549     case 1:
5550       return simplexizePol1();
5551     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5552         return simplexizePlanarFace5();
5553     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5554         return simplexizePlanarFace6();
5555     default:
5556       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)");
5557   }
5558 }
5559
5560 /*!
5561  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5562  * - 1D: INTERP_KERNEL::NORM_SEG2
5563  * - 2D: INTERP_KERNEL::NORM_TRI3
5564  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5565  *
5566  * This method is useful for users that need to use P1 field services as
5567  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5568  * All these methods need mesh support containing only simplex cells.
5569  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5570  *  \throw If the coordinates array is not set.
5571  *  \throw If the nodal connectivity of cells is not defined.
5572  *  \throw If \a this->getMeshDimension() < 1.
5573  */
5574 bool MEDCouplingUMesh::areOnlySimplexCells() const
5575 {
5576   checkFullyDefined();
5577   int mdim=getMeshDimension();
5578   if(mdim<1 || mdim>3)
5579     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5580   int nbCells=getNumberOfCells();
5581   const int *conn=_nodal_connec->getConstPointer();
5582   const int *connI=_nodal_connec_index->getConstPointer();
5583   for(int i=0;i<nbCells;i++)
5584     {
5585       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5586       if(!cm.isSimplex())
5587         return false;
5588     }
5589   return true;
5590 }
5591
5592 /*!
5593  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5594  */
5595 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5596 {
5597   checkConnectivityFullyDefined();
5598   if(getMeshDimension()!=2)
5599     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5600   int nbOfCells=getNumberOfCells();
5601   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5602   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5603   ret->alloc(nbOfCells+nbOfCutCells,1);
5604   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5605   int *retPt=ret->getPointer();
5606   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5607   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5608   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5609   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5610   int *pt=newConn->getPointer();
5611   int *ptI=newConnI->getPointer();
5612   ptI[0]=0;
5613   const int *oldc=_nodal_connec->getConstPointer();
5614   const int *ci=_nodal_connec_index->getConstPointer();
5615   for(int i=0;i<nbOfCells;i++,ci++)
5616     {
5617       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5618         {
5619           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5620             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5621           pt=std::copy(tmp,tmp+8,pt);
5622           ptI[1]=ptI[0]+4;
5623           ptI[2]=ptI[0]+8;
5624           *retPt++=i;
5625           *retPt++=i;
5626           ptI+=2;
5627         }
5628       else
5629         {
5630           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5631           ptI[1]=ptI[0]+ci[1]-ci[0];
5632           ptI++;
5633           *retPt++=i;
5634         }
5635     }
5636   _nodal_connec->decrRef();
5637   _nodal_connec=newConn.retn();
5638   _nodal_connec_index->decrRef();
5639   _nodal_connec_index=newConnI.retn();
5640   computeTypes();
5641   updateTime();
5642   return ret.retn();
5643 }
5644
5645 /*!
5646  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5647  */
5648 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5649 {
5650   checkConnectivityFullyDefined();
5651   if(getMeshDimension()!=2)
5652     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5653   int nbOfCells=getNumberOfCells();
5654   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5655   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5656   ret->alloc(nbOfCells+nbOfCutCells,1);
5657   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5658   int *retPt=ret->getPointer();
5659   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5660   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5661   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5662   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5663   int *pt=newConn->getPointer();
5664   int *ptI=newConnI->getPointer();
5665   ptI[0]=0;
5666   const int *oldc=_nodal_connec->getConstPointer();
5667   const int *ci=_nodal_connec_index->getConstPointer();
5668   for(int i=0;i<nbOfCells;i++,ci++)
5669     {
5670       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5671         {
5672           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5673             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5674           pt=std::copy(tmp,tmp+8,pt);
5675           ptI[1]=ptI[0]+4;
5676           ptI[2]=ptI[0]+8;
5677           *retPt++=i;
5678           *retPt++=i;
5679           ptI+=2;
5680         }
5681       else
5682         {
5683           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5684           ptI[1]=ptI[0]+ci[1]-ci[0];
5685           ptI++;
5686           *retPt++=i;
5687         }
5688     }
5689   _nodal_connec->decrRef();
5690   _nodal_connec=newConn.retn();
5691   _nodal_connec_index->decrRef();
5692   _nodal_connec_index=newConnI.retn();
5693   computeTypes();
5694   updateTime();
5695   return ret.retn();
5696 }
5697
5698 /*!
5699  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5700  */
5701 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5702 {
5703   checkConnectivityFullyDefined();
5704   if(getMeshDimension()!=3)
5705     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5706   int nbOfCells=getNumberOfCells();
5707   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5708   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5709   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5710   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5711   int *retPt=ret->getPointer();
5712   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5713   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5714   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5715   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5716   int *pt=newConn->getPointer();
5717   int *ptI=newConnI->getPointer();
5718   ptI[0]=0;
5719   const int *oldc=_nodal_connec->getConstPointer();
5720   const int *ci=_nodal_connec_index->getConstPointer();
5721   for(int i=0;i<nbOfCells;i++,ci++)
5722     {
5723       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5724         {
5725           for(int j=0;j<5;j++,pt+=5,ptI++)
5726             {
5727               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5728               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];
5729               *retPt++=i;
5730               ptI[1]=ptI[0]+5;
5731             }
5732         }
5733       else
5734         {
5735           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5736           ptI[1]=ptI[0]+ci[1]-ci[0];
5737           ptI++;
5738           *retPt++=i;
5739         }
5740     }
5741   _nodal_connec->decrRef();
5742   _nodal_connec=newConn.retn();
5743   _nodal_connec_index->decrRef();
5744   _nodal_connec_index=newConnI.retn();
5745   computeTypes();
5746   updateTime();
5747   return ret.retn();
5748 }
5749
5750 /*!
5751  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5752  */
5753 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5754 {
5755   checkConnectivityFullyDefined();
5756   if(getMeshDimension()!=3)
5757     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5758   int nbOfCells=getNumberOfCells();
5759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5760   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5761   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5762   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5763   int *retPt=ret->getPointer();
5764   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5765   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5766   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5767   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5768   int *pt=newConn->getPointer();
5769   int *ptI=newConnI->getPointer();
5770   ptI[0]=0;
5771   const int *oldc=_nodal_connec->getConstPointer();
5772   const int *ci=_nodal_connec_index->getConstPointer();
5773   for(int i=0;i<nbOfCells;i++,ci++)
5774     {
5775       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5776         {
5777           for(int j=0;j<6;j++,pt+=5,ptI++)
5778             {
5779               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5780               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];
5781               *retPt++=i;
5782               ptI[1]=ptI[0]+5;
5783             }
5784         }
5785       else
5786         {
5787           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5788           ptI[1]=ptI[0]+ci[1]-ci[0];
5789           ptI++;
5790           *retPt++=i;
5791         }
5792     }
5793   _nodal_connec->decrRef();
5794   _nodal_connec=newConn.retn();
5795   _nodal_connec_index->decrRef();
5796   _nodal_connec_index=newConnI.retn();
5797   computeTypes();
5798   updateTime();
5799   return ret.retn();
5800 }
5801
5802 /*!
5803  * 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.
5804  * This method completly ignore coordinates.
5805  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5806  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5807  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5808  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5809  */
5810 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5811 {
5812   checkFullyDefined();
5813   if(getMeshDimension()!=2)
5814     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5815   int nbOfCells=getNumberOfCells();
5816   int *connI=_nodal_connec_index->getPointer();
5817   int newConnLgth=0;
5818   for(int i=0;i<nbOfCells;i++,connI++)
5819     {
5820       int offset=descIndex[i];
5821       int nbOfEdges=descIndex[i+1]-offset;
5822       //
5823       bool ddirect=desc[offset+nbOfEdges-1]>0;
5824       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5825       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5826       for(int j=0;j<nbOfEdges;j++)
5827         {
5828           bool direct=desc[offset+j]>0;
5829           int edgeId=std::abs(desc[offset+j])-1;
5830           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5831             {
5832               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5833               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5834               int ref2=direct?id1:id2;
5835               if(ref==ref2)
5836                 {
5837                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5838                   newConnLgth+=nbOfSubNodes-1;
5839                   ref=direct?id2:id1;
5840                 }
5841               else
5842                 {
5843                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5844                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5845                 }
5846             }
5847           else
5848             {
5849               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5850             }
5851         }
5852       newConnLgth++;//+1 is for cell type
5853       connI[1]=newConnLgth;
5854     }
5855   //
5856   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5857   newConn->alloc(newConnLgth,1);
5858   int *work=newConn->getPointer();
5859   for(int i=0;i<nbOfCells;i++)
5860     {
5861       *work++=INTERP_KERNEL::NORM_POLYGON;
5862       int offset=descIndex[i];
5863       int nbOfEdges=descIndex[i+1]-offset;
5864       for(int j=0;j<nbOfEdges;j++)
5865         {
5866           bool direct=desc[offset+j]>0;
5867           int edgeId=std::abs(desc[offset+j])-1;
5868           if(direct)
5869             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5870           else
5871             {
5872               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5873               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5874               work=std::copy(it,it+nbOfSubNodes-1,work);
5875             }
5876         }
5877     }
5878   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5879   _types.clear();
5880   if(nbOfCells>0)
5881     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5882 }
5883
5884 /*!
5885  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5886  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5887  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5888  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5889  * so it can be useful to call mergeNodes() before calling this method.
5890  *  \throw If \a this->getMeshDimension() <= 1.
5891  *  \throw If the coordinates array is not set.
5892  *  \throw If the nodal connectivity of cells is not defined.
5893  */
5894 void MEDCouplingUMesh::convertDegeneratedCells()
5895 {
5896   checkFullyDefined();
5897   if(getMeshDimension()<=1)
5898     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5899   int nbOfCells=getNumberOfCells();
5900   if(nbOfCells<1)
5901     return ;
5902   int initMeshLgth=getMeshLength();
5903   int *conn=_nodal_connec->getPointer();
5904   int *index=_nodal_connec_index->getPointer();
5905   int posOfCurCell=0;
5906   int newPos=0;
5907   int lgthOfCurCell;
5908   for(int i=0;i<nbOfCells;i++)
5909     {
5910       lgthOfCurCell=index[i+1]-posOfCurCell;
5911       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5912       int newLgth;
5913       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5914                                                                                                      conn+newPos+1,newLgth);
5915       conn[newPos]=newType;
5916       newPos+=newLgth+1;
5917       posOfCurCell=index[i+1];
5918       index[i+1]=newPos;
5919     }
5920   if(newPos!=initMeshLgth)
5921     _nodal_connec->reAlloc(newPos);
5922   computeTypes();
5923 }
5924
5925 /*!
5926  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5927  * A cell is considered to be oriented correctly if an angle between its
5928  * normal vector and a given vector is less than \c PI / \c 2.
5929  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5930  *         cells. 
5931  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5932  *         checked.
5933  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5934  *         is not cleared before filling in.
5935  *  \throw If \a this->getMeshDimension() != 2.
5936  *  \throw If \a this->getSpaceDimension() != 3.
5937  *
5938  *  \if ENABLE_EXAMPLES
5939  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5940  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5941  *  \endif
5942  */
5943 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5944 {
5945   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5946     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5947   int nbOfCells=getNumberOfCells();
5948   const int *conn=_nodal_connec->getConstPointer();
5949   const int *connI=_nodal_connec_index->getConstPointer();
5950   const double *coordsPtr=_coords->getConstPointer();
5951   for(int i=0;i<nbOfCells;i++)
5952     {
5953       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5954       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5955         {
5956           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5957           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5958             cells.push_back(i);
5959         }
5960     }
5961 }
5962
5963 /*!
5964  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5965  * considered to be oriented correctly if an angle between its normal vector and a
5966  * given vector is less than \c PI / \c 2. 
5967  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5968  *         cells. 
5969  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5970  *         checked.
5971  *  \throw If \a this->getMeshDimension() != 2.
5972  *  \throw If \a this->getSpaceDimension() != 3.
5973  *
5974  *  \if ENABLE_EXAMPLES
5975  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5976  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5977  *  \endif
5978  *
5979  *  \sa changeOrientationOfCells
5980  */
5981 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5982 {
5983   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5984     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5985   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
5986   const int *connI(_nodal_connec_index->getConstPointer());
5987   const double *coordsPtr(_coords->getConstPointer());
5988   bool isModified(false);
5989   for(int i=0;i<nbOfCells;i++)
5990     {
5991       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5992       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5993         {
5994           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
5995           bool isQuadratic(cm.isQuadratic());
5996           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5997             {
5998               isModified=true;
5999               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6000             }
6001         }
6002     }
6003   if(isModified)
6004     _nodal_connec->declareAsNew();
6005   updateTime();
6006 }
6007
6008 /*!
6009  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6010  *
6011  * \sa orientCorrectly2DCells
6012  */
6013 void MEDCouplingUMesh::changeOrientationOfCells()
6014 {
6015   int mdim(getMeshDimension());
6016   if(mdim!=2 && mdim!=1)
6017     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6018   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6019   const int *connI(_nodal_connec_index->getConstPointer());
6020   if(mdim==2)
6021     {//2D
6022       for(int i=0;i<nbOfCells;i++)
6023         {
6024           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6025           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6026           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6027         }
6028     }
6029   else
6030     {//1D
6031       for(int i=0;i<nbOfCells;i++)
6032         {
6033           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6034           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6035           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6036         }
6037     }
6038 }
6039
6040 /*!
6041  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6042  * oriented facets. The normal vector of the facet should point out of the cell.
6043  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6044  *         is not cleared before filling in.
6045  *  \throw If \a this->getMeshDimension() != 3.
6046  *  \throw If \a this->getSpaceDimension() != 3.
6047  *  \throw If the coordinates array is not set.
6048  *  \throw If the nodal connectivity of cells is not defined.
6049  *
6050  *  \if ENABLE_EXAMPLES
6051  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6052  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6053  *  \endif
6054  */
6055 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6056 {
6057   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6058     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6059   int nbOfCells=getNumberOfCells();
6060   const int *conn=_nodal_connec->getConstPointer();
6061   const int *connI=_nodal_connec_index->getConstPointer();
6062   const double *coordsPtr=_coords->getConstPointer();
6063   for(int i=0;i<nbOfCells;i++)
6064     {
6065       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6066       if(type==INTERP_KERNEL::NORM_POLYHED)
6067         {
6068           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6069             cells.push_back(i);
6070         }
6071     }
6072 }
6073
6074 /*!
6075  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6076  * out of the cell. 
6077  *  \throw If \a this->getMeshDimension() != 3.
6078  *  \throw If \a this->getSpaceDimension() != 3.
6079  *  \throw If the coordinates array is not set.
6080  *  \throw If the nodal connectivity of cells is not defined.
6081  *  \throw If the reparation fails.
6082  *
6083  *  \if ENABLE_EXAMPLES
6084  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6085  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6086  *  \endif
6087  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6088  */
6089 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6090 {
6091   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6092     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6093   int nbOfCells=getNumberOfCells();
6094   int *conn=_nodal_connec->getPointer();
6095   const int *connI=_nodal_connec_index->getConstPointer();
6096   const double *coordsPtr=_coords->getConstPointer();
6097   for(int i=0;i<nbOfCells;i++)
6098     {
6099       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6100       if(type==INTERP_KERNEL::NORM_POLYHED)
6101         {
6102           try
6103           {
6104               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6105                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6106           }
6107           catch(INTERP_KERNEL::Exception& e)
6108           {
6109               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6110               throw INTERP_KERNEL::Exception(oss.str().c_str());
6111           }
6112         }
6113     }
6114   updateTime();
6115 }
6116
6117 /*!
6118  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6119  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6120  * according to which the first facet of the cell should be oriented to have the normal vector
6121  * pointing out of cell.
6122  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6123  *         cells. The caller is to delete this array using decrRef() as it is no more
6124  *         needed. 
6125  *  \throw If \a this->getMeshDimension() != 3.
6126  *  \throw If \a this->getSpaceDimension() != 3.
6127  *  \throw If the coordinates array is not set.
6128  *  \throw If the nodal connectivity of cells is not defined.
6129  *
6130  *  \if ENABLE_EXAMPLES
6131  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6132  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6133  *  \endif
6134  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6135  */
6136 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6137 {
6138   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6139   if(getMeshDimension()!=3)
6140     throw INTERP_KERNEL::Exception(msg);
6141   int spaceDim=getSpaceDimension();
6142   if(spaceDim!=3)
6143     throw INTERP_KERNEL::Exception(msg);
6144   //
6145   int nbOfCells=getNumberOfCells();
6146   int *conn=_nodal_connec->getPointer();
6147   const int *connI=_nodal_connec_index->getConstPointer();
6148   const double *coo=getCoords()->getConstPointer();
6149   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6150   for(int i=0;i<nbOfCells;i++)
6151     {
6152       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6153       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6154         {
6155           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6156             {
6157               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6158               cells->pushBackSilent(i);
6159             }
6160         }
6161     }
6162   return cells.retn();
6163 }
6164
6165 /*!
6166  * This method is a faster method to correct orientation of all 3D cells in \a this.
6167  * 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.
6168  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6169  * 
6170  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6171  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6172  */
6173 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6174 {
6175   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6176     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6177   int nbOfCells=getNumberOfCells();
6178   int *conn=_nodal_connec->getPointer();
6179   const int *connI=_nodal_connec_index->getConstPointer();
6180   const double *coordsPtr=_coords->getConstPointer();
6181   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6182   for(int i=0;i<nbOfCells;i++)
6183     {
6184       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6185       switch(type)
6186       {
6187         case INTERP_KERNEL::NORM_TETRA4:
6188           {
6189             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6190               {
6191                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6192                 ret->pushBackSilent(i);
6193               }
6194             break;
6195           }
6196         case INTERP_KERNEL::NORM_PYRA5:
6197           {
6198             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6199               {
6200                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6201                 ret->pushBackSilent(i);
6202               }
6203             break;
6204           }
6205         case INTERP_KERNEL::NORM_PENTA6:
6206         case INTERP_KERNEL::NORM_HEXA8:
6207         case INTERP_KERNEL::NORM_HEXGP12:
6208           {
6209             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6210               {
6211                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6212                 ret->pushBackSilent(i);
6213               }
6214             break;
6215           }
6216         case INTERP_KERNEL::NORM_POLYHED:
6217           {
6218             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6219               {
6220                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6221                 ret->pushBackSilent(i);
6222               }
6223             break;
6224           }
6225         default:
6226           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 !");
6227       }
6228     }
6229   updateTime();
6230   return ret.retn();
6231 }
6232
6233 /*!
6234  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6235  * If it is not the case an exception will be thrown.
6236  * This method is fast because the first cell of \a this is used to compute the plane.
6237  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6238  * \param pos output of size at least 3 used to store a point owned of searched plane.
6239  */
6240 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6241 {
6242   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6243     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6244   const int *conn=_nodal_connec->getConstPointer();
6245   const int *connI=_nodal_connec_index->getConstPointer();
6246   const double *coordsPtr=_coords->getConstPointer();
6247   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6248   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6249 }
6250
6251 /*!
6252  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6253  * cells. Currently cells of the following types are treated:
6254  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6255  * For a cell of other type an exception is thrown.
6256  * Space dimension of a 2D mesh can be either 2 or 3.
6257  * The Edge Ratio of a cell \f$t\f$ is: 
6258  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6259  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6260  *  the smallest edge lengths of \f$t\f$.
6261  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6262  *          cells and one time, lying on \a this mesh. The caller is to delete this
6263  *          field using decrRef() as it is no more needed. 
6264  *  \throw If the coordinates array is not set.
6265  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6266  *  \throw If the connectivity data array has more than one component.
6267  *  \throw If the connectivity data array has a named component.
6268  *  \throw If the connectivity index data array has more than one component.
6269  *  \throw If the connectivity index data array has a named component.
6270  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6271  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6272  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6273  */
6274 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6275 {
6276   checkCoherency();
6277   int spaceDim=getSpaceDimension();
6278   int meshDim=getMeshDimension();
6279   if(spaceDim!=2 && spaceDim!=3)
6280     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6281   if(meshDim!=2 && meshDim!=3)
6282     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6283   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6284   ret->setMesh(this);
6285   int nbOfCells=getNumberOfCells();
6286   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6287   arr->alloc(nbOfCells,1);
6288   double *pt=arr->getPointer();
6289   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6290   const int *conn=_nodal_connec->getConstPointer();
6291   const int *connI=_nodal_connec_index->getConstPointer();
6292   const double *coo=_coords->getConstPointer();
6293   double tmp[12];
6294   for(int i=0;i<nbOfCells;i++,pt++)
6295     {
6296       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6297       switch(t)
6298       {
6299         case INTERP_KERNEL::NORM_TRI3:
6300           {
6301             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6302             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6303             break;
6304           }
6305         case INTERP_KERNEL::NORM_QUAD4:
6306           {
6307             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6308             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6309             break;
6310           }
6311         case INTERP_KERNEL::NORM_TETRA4:
6312           {
6313             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6314             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6315             break;
6316           }
6317         default:
6318           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6319       }
6320       conn+=connI[i+1]-connI[i];
6321     }
6322   ret->setName("EdgeRatio");
6323   ret->synchronizeTimeWithSupport();
6324   return ret.retn();
6325 }
6326
6327 /*!
6328  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6329  * cells. Currently cells of the following types are treated:
6330  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6331  * For a cell of other type an exception is thrown.
6332  * Space dimension of a 2D mesh can be either 2 or 3.
6333  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6334  *          cells and one time, lying on \a this mesh. The caller is to delete this
6335  *          field using decrRef() as it is no more needed. 
6336  *  \throw If the coordinates array is not set.
6337  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6338  *  \throw If the connectivity data array has more than one component.
6339  *  \throw If the connectivity data array has a named component.
6340  *  \throw If the connectivity index data array has more than one component.
6341  *  \throw If the connectivity index data array has a named component.
6342  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6343  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6344  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6345  */
6346 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6347 {
6348   checkCoherency();
6349   int spaceDim=getSpaceDimension();
6350   int meshDim=getMeshDimension();
6351   if(spaceDim!=2 && spaceDim!=3)
6352     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6353   if(meshDim!=2 && meshDim!=3)
6354     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6355   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6356   ret->setMesh(this);
6357   int nbOfCells=getNumberOfCells();
6358   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6359   arr->alloc(nbOfCells,1);
6360   double *pt=arr->getPointer();
6361   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6362   const int *conn=_nodal_connec->getConstPointer();
6363   const int *connI=_nodal_connec_index->getConstPointer();
6364   const double *coo=_coords->getConstPointer();
6365   double tmp[12];
6366   for(int i=0;i<nbOfCells;i++,pt++)
6367     {
6368       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6369       switch(t)
6370       {
6371         case INTERP_KERNEL::NORM_TRI3:
6372           {
6373             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6374             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6375             break;
6376           }
6377         case INTERP_KERNEL::NORM_QUAD4:
6378           {
6379             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6380             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6381             break;
6382           }
6383         case INTERP_KERNEL::NORM_TETRA4:
6384           {
6385             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6386             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6387             break;
6388           }
6389         default:
6390           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6391       }
6392       conn+=connI[i+1]-connI[i];
6393     }
6394   ret->setName("AspectRatio");
6395   ret->synchronizeTimeWithSupport();
6396   return ret.retn();
6397 }
6398
6399 /*!
6400  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6401  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6402  * treated: INTERP_KERNEL::NORM_QUAD4.
6403  * For a cell of other type an exception is thrown.
6404  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6405  *          cells and one time, lying on \a this mesh. The caller is to delete this
6406  *          field using decrRef() as it is no more needed. 
6407  *  \throw If the coordinates array is not set.
6408  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6409  *  \throw If the connectivity data array has more than one component.
6410  *  \throw If the connectivity data array has a named component.
6411  *  \throw If the connectivity index data array has more than one component.
6412  *  \throw If the connectivity index data array has a named component.
6413  *  \throw If \a this->getMeshDimension() != 2.
6414  *  \throw If \a this->getSpaceDimension() != 3.
6415  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6416  */
6417 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6418 {
6419   checkCoherency();
6420   int spaceDim=getSpaceDimension();
6421   int meshDim=getMeshDimension();
6422   if(spaceDim!=3)
6423     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6424   if(meshDim!=2)
6425     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6426   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6427   ret->setMesh(this);
6428   int nbOfCells=getNumberOfCells();
6429   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6430   arr->alloc(nbOfCells,1);
6431   double *pt=arr->getPointer();
6432   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6433   const int *conn=_nodal_connec->getConstPointer();
6434   const int *connI=_nodal_connec_index->getConstPointer();
6435   const double *coo=_coords->getConstPointer();
6436   double tmp[12];
6437   for(int i=0;i<nbOfCells;i++,pt++)
6438     {
6439       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6440       switch(t)
6441       {
6442         case INTERP_KERNEL::NORM_QUAD4:
6443           {
6444             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6445             *pt=INTERP_KERNEL::quadWarp(tmp);
6446             break;
6447           }
6448         default:
6449           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6450       }
6451       conn+=connI[i+1]-connI[i];
6452     }
6453   ret->setName("Warp");
6454   ret->synchronizeTimeWithSupport();
6455   return ret.retn();
6456 }
6457
6458
6459 /*!
6460  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6461  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6462  * treated: INTERP_KERNEL::NORM_QUAD4.
6463  * For a cell of other type an exception is thrown.
6464  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6465  *          cells and one time, lying on \a this mesh. The caller is to delete this
6466  *          field using decrRef() as it is no more needed. 
6467  *  \throw If the coordinates array is not set.
6468  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6469  *  \throw If the connectivity data array has more than one component.
6470  *  \throw If the connectivity data array has a named component.
6471  *  \throw If the connectivity index data array has more than one component.
6472  *  \throw If the connectivity index data array has a named component.
6473  *  \throw If \a this->getMeshDimension() != 2.
6474  *  \throw If \a this->getSpaceDimension() != 3.
6475  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6476  */
6477 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6478 {
6479   checkCoherency();
6480   int spaceDim=getSpaceDimension();
6481   int meshDim=getMeshDimension();
6482   if(spaceDim!=3)
6483     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6484   if(meshDim!=2)
6485     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6486   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6487   ret->setMesh(this);
6488   int nbOfCells=getNumberOfCells();
6489   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6490   arr->alloc(nbOfCells,1);
6491   double *pt=arr->getPointer();
6492   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6493   const int *conn=_nodal_connec->getConstPointer();
6494   const int *connI=_nodal_connec_index->getConstPointer();
6495   const double *coo=_coords->getConstPointer();
6496   double tmp[12];
6497   for(int i=0;i<nbOfCells;i++,pt++)
6498     {
6499       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6500       switch(t)
6501       {
6502         case INTERP_KERNEL::NORM_QUAD4:
6503           {
6504             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6505             *pt=INTERP_KERNEL::quadSkew(tmp);
6506             break;
6507           }
6508         default:
6509           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6510       }
6511       conn+=connI[i+1]-connI[i];
6512     }
6513   ret->setName("Skew");
6514   ret->synchronizeTimeWithSupport();
6515   return ret.retn();
6516 }
6517
6518 /*!
6519  * This method aggregate the bbox of each cell and put it into bbox parameter.
6520  * 
6521  * \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)
6522  *                         For all other cases this input parameter is ignored.
6523  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6524  * 
6525  * \throw If \a this is not fully set (coordinates and connectivity).
6526  * \throw If a cell in \a this has no valid nodeId.
6527  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6528  */
6529 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6530 {
6531   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6532   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.
6533     return getBoundingBoxForBBTreeFast();
6534   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6535     {
6536       bool presenceOfQuadratic(false);
6537       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6538         {
6539           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6540           if(cm.isQuadratic())
6541             presenceOfQuadratic=true;
6542         }
6543       if(!presenceOfQuadratic)
6544         return getBoundingBoxForBBTreeFast();
6545       if(mDim==2 && sDim==2)
6546         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6547       else
6548         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6549     }
6550   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) !");
6551 }
6552
6553 /*!
6554  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6555  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6556  * 
6557  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6558  * 
6559  * \throw If \a this is not fully set (coordinates and connectivity).
6560  * \throw If a cell in \a this has no valid nodeId.
6561  */
6562 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6563 {
6564   checkFullyDefined();
6565   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6566   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6567   double *bbox(ret->getPointer());
6568   for(int i=0;i<nbOfCells*spaceDim;i++)
6569     {
6570       bbox[2*i]=std::numeric_limits<double>::max();
6571       bbox[2*i+1]=-std::numeric_limits<double>::max();
6572     }
6573   const double *coordsPtr(_coords->getConstPointer());
6574   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6575   for(int i=0;i<nbOfCells;i++)
6576     {
6577       int offset=connI[i]+1;
6578       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6579       for(int j=0;j<nbOfNodesForCell;j++)
6580         {
6581           int nodeId=conn[offset+j];
6582           if(nodeId>=0 && nodeId<nbOfNodes)
6583             {
6584               for(int k=0;k<spaceDim;k++)
6585                 {
6586                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6587                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6588                 }
6589               kk++;
6590             }
6591         }
6592       if(kk==0)
6593         {
6594           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6595           throw INTERP_KERNEL::Exception(oss.str().c_str());
6596         }
6597     }
6598   return ret.retn();
6599 }
6600
6601 /*!
6602  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6603  * useful for 2D meshes having quadratic cells
6604  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6605  * the two extremities of the arc of circle).
6606  * 
6607  * \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)
6608  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6609  * \throw If \a this is not fully defined.
6610  * \throw If \a this is not a mesh with meshDimension equal to 2.
6611  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6612  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6613  */
6614 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6615 {
6616   checkFullyDefined();
6617   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6618   if(spaceDim!=2 || mDim!=2)
6619     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!");
6620   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6621   double *bbox(ret->getPointer());
6622   const double *coords(_coords->getConstPointer());
6623   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6624   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6625     {
6626       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6627       int sz(connI[1]-connI[0]-1);
6628       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6629       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6630       INTERP_KERNEL::QuadraticPolygon *pol(0);
6631       for(int j=0;j<sz;j++)
6632         {
6633           int nodeId(conn[*connI+1+j]);
6634           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6635         }
6636       if(!cm.isQuadratic())
6637         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6638       else
6639         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6640       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6641       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6642     }
6643   return ret.retn();
6644 }
6645
6646 /*!
6647  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6648  * useful for 2D meshes having quadratic cells
6649  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6650  * the two extremities of the arc of circle).
6651  * 
6652  * \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)
6653  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6654  * \throw If \a this is not fully defined.
6655  * \throw If \a this is not a mesh with meshDimension equal to 1.
6656  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6657  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6658  */
6659 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6660 {
6661   checkFullyDefined();
6662   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6663   if(spaceDim!=2 || mDim!=1)
6664     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!");
6665   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6666   double *bbox(ret->getPointer());
6667   const double *coords(_coords->getConstPointer());
6668   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6669   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6670     {
6671       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6672       int sz(connI[1]-connI[0]-1);
6673       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6674       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6675       INTERP_KERNEL::Edge *edge(0);
6676       for(int j=0;j<sz;j++)
6677         {
6678           int nodeId(conn[*connI+1+j]);
6679           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6680         }
6681       if(!cm.isQuadratic())
6682         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6683       else
6684         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6685       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6686       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6687     }
6688   return ret.retn();
6689 }
6690
6691 /// @cond INTERNAL
6692
6693 namespace ParaMEDMEMImpl
6694 {
6695   class ConnReader
6696   {
6697   public:
6698     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6699     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6700   private:
6701     const int *_conn;
6702     int _val;
6703   };
6704
6705   class ConnReader2
6706   {
6707   public:
6708     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6709     bool operator() (const int& pos) { return _conn[pos]==_val; }
6710   private:
6711     const int *_conn;
6712     int _val;
6713   };
6714 }
6715
6716 /// @endcond
6717
6718 /*!
6719  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6720  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6721  * \a this is composed in cell types.
6722  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6723  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6724  * This parameter is kept only for compatibility with other methode listed above.
6725  */
6726 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6727 {
6728   checkConnectivityFullyDefined();
6729   const int *conn=_nodal_connec->getConstPointer();
6730   const int *connI=_nodal_connec_index->getConstPointer();
6731   const int *work=connI;
6732   int nbOfCells=getNumberOfCells();
6733   std::size_t n=getAllGeoTypes().size();
6734   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6735   std::set<INTERP_KERNEL::NormalizedCellType> types;
6736   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6737     {
6738       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6739       if(types.find(typ)!=types.end())
6740         {
6741           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6742           oss << " is not contiguous !";
6743           throw INTERP_KERNEL::Exception(oss.str().c_str());
6744         }
6745       types.insert(typ);
6746       ret[3*i]=typ;
6747       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6748       ret[3*i+1]=(int)std::distance(work,work2);
6749       work=work2;
6750     }
6751   return ret;
6752 }
6753
6754 /*!
6755  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6756  * only for types cell, type node is not managed.
6757  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6758  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6759  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6760  * If 2 or more same geometric type is in \a code and exception is thrown too.
6761  *
6762  * This method firstly checks
6763  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6764  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6765  * an exception is thrown too.
6766  * 
6767  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6768  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6769  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6770  */
6771 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6772 {
6773   if(code.empty())
6774     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6775   std::size_t sz=code.size();
6776   std::size_t n=sz/3;
6777   if(sz%3!=0)
6778     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6779   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6780   int nb=0;
6781   bool isNoPflUsed=true;
6782   for(std::size_t i=0;i<n;i++)
6783     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6784       {
6785         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6786         nb+=code[3*i+1];
6787         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6788           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6789         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6790       }
6791   if(types.size()!=n)
6792     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6793   if(isNoPflUsed)
6794     {
6795       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6796         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6797       if(types.size()==_types.size())
6798         return 0;
6799     }
6800   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6801   ret->alloc(nb,1);
6802   int *retPtr=ret->getPointer();
6803   const int *connI=_nodal_connec_index->getConstPointer();
6804   const int *conn=_nodal_connec->getConstPointer();
6805   int nbOfCells=getNumberOfCells();
6806   const int *i=connI;
6807   int kk=0;
6808   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6809     {
6810       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6811       int offset=(int)std::distance(connI,i);
6812       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6813       int nbOfCellsOfCurType=(int)std::distance(i,j);
6814       if(code[3*kk+2]==-1)
6815         for(int k=0;k<nbOfCellsOfCurType;k++)
6816           *retPtr++=k+offset;
6817       else
6818         {
6819           int idInIdsPerType=code[3*kk+2];
6820           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6821             {
6822               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6823               if(zePfl)
6824                 {
6825                   zePfl->checkAllocated();
6826                   if(zePfl->getNumberOfComponents()==1)
6827                     {
6828                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6829                         {
6830                           if(*k>=0 && *k<nbOfCellsOfCurType)
6831                             *retPtr=(*k)+offset;
6832                           else
6833                             {
6834                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6835                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6836                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6837                             }
6838                         }
6839                     }
6840                   else
6841                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6842                 }
6843               else
6844                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6845             }
6846           else
6847             {
6848               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6849               oss << " should be in [0," << idsPerType.size() << ") !";
6850               throw INTERP_KERNEL::Exception(oss.str().c_str());
6851             }
6852         }
6853       i=j;
6854     }
6855   return ret.retn();
6856 }
6857
6858 /*!
6859  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6860  * 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.
6861  * 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.
6862  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6863  * 
6864  * \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.
6865  * \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,
6866  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6867  * \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.
6868  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6869  * \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
6870  */
6871 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6872 {
6873   if(!profile)
6874     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6875   if(profile->getNumberOfComponents()!=1)
6876     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6877   checkConnectivityFullyDefined();
6878   const int *conn=_nodal_connec->getConstPointer();
6879   const int *connI=_nodal_connec_index->getConstPointer();
6880   int nbOfCells=getNumberOfCells();
6881   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6882   std::vector<int> typeRangeVals(1);
6883   for(const int *i=connI;i!=connI+nbOfCells;)
6884     {
6885       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6886       if(std::find(types.begin(),types.end(),curType)!=types.end())
6887         {
6888           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6889         }
6890       types.push_back(curType);
6891       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6892       typeRangeVals.push_back((int)std::distance(connI,i));
6893     }
6894   //
6895   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6896   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6897   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6898   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6899   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6900   //
6901   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6902   code.resize(3*nbOfCastsFinal);
6903   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6904   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6905   for(int i=0;i<nbOfCastsFinal;i++)
6906     {
6907       int castId=castsPresent->getIJ(i,0);
6908       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6909       idsInPflPerType2.push_back(tmp3);
6910       code[3*i]=(int)types[castId];
6911       code[3*i+1]=tmp3->getNumberOfTuples();
6912       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6913       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6914         {
6915           tmp4->copyStringInfoFrom(*profile);
6916           idsPerType2.push_back(tmp4);
6917           code[3*i+2]=(int)idsPerType2.size()-1;
6918         }
6919       else
6920         {
6921           code[3*i+2]=-1;
6922         }
6923     }
6924   std::size_t sz2=idsInPflPerType2.size();
6925   idsInPflPerType.resize(sz2);
6926   for(std::size_t i=0;i<sz2;i++)
6927     {
6928       DataArrayInt *locDa=idsInPflPerType2[i];
6929       locDa->incrRef();
6930       idsInPflPerType[i]=locDa;
6931     }
6932   std::size_t sz=idsPerType2.size();
6933   idsPerType.resize(sz);
6934   for(std::size_t i=0;i<sz;i++)
6935     {
6936       DataArrayInt *locDa=idsPerType2[i];
6937       locDa->incrRef();
6938       idsPerType[i]=locDa;
6939     }
6940 }
6941
6942 /*!
6943  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6944  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6945  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6946  * 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.
6947  */
6948 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6949 {
6950   checkFullyDefined();
6951   nM1LevMesh->checkFullyDefined();
6952   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6953     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6954   if(_coords!=nM1LevMesh->getCoords())
6955     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6956   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6957   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6958   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6959   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6960   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6961   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6962   tmp->setConnectivity(tmp0,tmp1);
6963   tmp->renumberCells(ret0->getConstPointer(),false);
6964   revDesc=tmp->getNodalConnectivity();
6965   revDescIndx=tmp->getNodalConnectivityIndex();
6966   DataArrayInt *ret=0;
6967   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6968     {
6969       int tmp2;
6970       ret->getMaxValue(tmp2);
6971       ret->decrRef();
6972       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6973       throw INTERP_KERNEL::Exception(oss.str().c_str());
6974     }
6975   nM1LevMeshIds=ret;
6976   //
6977   revDesc->incrRef();
6978   revDescIndx->incrRef();
6979   ret1->incrRef();
6980   ret0->incrRef();
6981   meshnM1Old2New=ret0;
6982   return ret1;
6983 }
6984
6985 /*!
6986  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6987  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6988  * in "Old to New" mode.
6989  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6990  *          this array using decrRef() as it is no more needed.
6991  *  \throw If the nodal connectivity of cells is not defined.
6992  */
6993 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6994 {
6995   checkConnectivityFullyDefined();
6996   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6997   renumberCells(ret->getConstPointer(),false);
6998   return ret.retn();
6999 }
7000
7001 /*!
7002  * This methods checks that cells are sorted by their types.
7003  * This method makes asumption (no check) that connectivity is correctly set before calling.
7004  */
7005 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7006 {
7007   checkFullyDefined();
7008   const int *conn=_nodal_connec->getConstPointer();
7009   const int *connI=_nodal_connec_index->getConstPointer();
7010   int nbOfCells=getNumberOfCells();
7011   std::set<INTERP_KERNEL::NormalizedCellType> types;
7012   for(const int *i=connI;i!=connI+nbOfCells;)
7013     {
7014       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7015       if(types.find(curType)!=types.end())
7016         return false;
7017       types.insert(curType);
7018       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7019     }
7020   return true;
7021 }
7022
7023 /*!
7024  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7025  * The geometric type order is specified by MED file.
7026  * 
7027  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7028  */
7029 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7030 {
7031   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7032 }
7033
7034 /*!
7035  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7036  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7037  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7038  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7039  */
7040 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7041 {
7042   checkFullyDefined();
7043   const int *conn=_nodal_connec->getConstPointer();
7044   const int *connI=_nodal_connec_index->getConstPointer();
7045   int nbOfCells=getNumberOfCells();
7046   if(nbOfCells==0)
7047     return true;
7048   int lastPos=-1;
7049   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7050   for(const int *i=connI;i!=connI+nbOfCells;)
7051     {
7052       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7053       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7054       if(isTypeExists!=orderEnd)
7055         {
7056           int pos=(int)std::distance(orderBg,isTypeExists);
7057           if(pos<=lastPos)
7058             return false;
7059           lastPos=pos;
7060           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7061         }
7062       else
7063         {
7064           if(sg.find(curType)==sg.end())
7065             {
7066               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7067               sg.insert(curType);
7068             }
7069           else
7070             return false;
7071         }
7072     }
7073   return true;
7074 }
7075
7076 /*!
7077  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7078  * 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
7079  * 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'.
7080  */
7081 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7082 {
7083   checkConnectivityFullyDefined();
7084   int nbOfCells=getNumberOfCells();
7085   const int *conn=_nodal_connec->getConstPointer();
7086   const int *connI=_nodal_connec_index->getConstPointer();
7087   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7088   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7089   tmpa->alloc(nbOfCells,1);
7090   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7091   tmpb->fillWithZero();
7092   int *tmp=tmpa->getPointer();
7093   int *tmp2=tmpb->getPointer();
7094   for(const int *i=connI;i!=connI+nbOfCells;i++)
7095     {
7096       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7097       if(where!=orderEnd)
7098         {
7099           int pos=(int)std::distance(orderBg,where);
7100           tmp2[pos]++;
7101           tmp[std::distance(connI,i)]=pos;
7102         }
7103       else
7104         {
7105           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7106           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7107           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7108           throw INTERP_KERNEL::Exception(oss.str().c_str());
7109         }
7110     }
7111   nbPerType=tmpb.retn();
7112   return tmpa.retn();
7113 }
7114
7115 /*!
7116  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7117  *
7118  * \return a new object containing the old to new correspondance.
7119  *
7120  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7121  */
7122 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7123 {
7124   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7125 }
7126
7127 /*!
7128  * 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.
7129  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7130  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7131  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7132  */
7133 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7134 {
7135   DataArrayInt *nbPerType=0;
7136   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7137   nbPerType->decrRef();
7138   return tmpa->buildPermArrPerLevel();
7139 }
7140
7141 /*!
7142  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7143  * The number of cells remains unchanged after the call of this method.
7144  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7145  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7146  *
7147  * \return the array giving the correspondance old to new.
7148  */
7149 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7150 {
7151   checkFullyDefined();
7152   computeTypes();
7153   const int *conn=_nodal_connec->getConstPointer();
7154   const int *connI=_nodal_connec_index->getConstPointer();
7155   int nbOfCells=getNumberOfCells();
7156   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7157   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7158     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7159       {
7160         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7161         types.push_back(curType);
7162         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7163       }
7164   DataArrayInt *ret=DataArrayInt::New();
7165   ret->alloc(nbOfCells,1);
7166   int *retPtr=ret->getPointer();
7167   std::fill(retPtr,retPtr+nbOfCells,-1);
7168   int newCellId=0;
7169   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7170     {
7171       for(const int *i=connI;i!=connI+nbOfCells;i++)
7172         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7173           retPtr[std::distance(connI,i)]=newCellId++;
7174     }
7175   renumberCells(retPtr,false);
7176   return ret;
7177 }
7178
7179 /*!
7180  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7181  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7182  * This method makes asumption that connectivity is correctly set before calling.
7183  */
7184 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7185 {
7186   checkConnectivityFullyDefined();
7187   const int *conn=_nodal_connec->getConstPointer();
7188   const int *connI=_nodal_connec_index->getConstPointer();
7189   int nbOfCells=getNumberOfCells();
7190   std::vector<MEDCouplingUMesh *> ret;
7191   for(const int *i=connI;i!=connI+nbOfCells;)
7192     {
7193       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7194       int beginCellId=(int)std::distance(connI,i);
7195       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7196       int endCellId=(int)std::distance(connI,i);
7197       int sz=endCellId-beginCellId;
7198       int *cells=new int[sz];
7199       for(int j=0;j<sz;j++)
7200         cells[j]=beginCellId+j;
7201       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7202       delete [] cells;
7203       ret.push_back(m);
7204     }
7205   return ret;
7206 }
7207
7208 /*!
7209  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7210  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7211  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7212  *
7213  * \return a newly allocated instance, that the caller must manage.
7214  * \throw If \a this contains more than one geometric type.
7215  * \throw If the nodal connectivity of \a this is not fully defined.
7216  * \throw If the internal data is not coherent.
7217  */
7218 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7219 {
7220   checkConnectivityFullyDefined();
7221   if(_types.size()!=1)
7222     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7223   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7224   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7225   ret->setCoords(getCoords());
7226   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7227   if(retC)
7228     {
7229       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7230       retC->setNodalConnectivity(c);
7231     }
7232   else
7233     {
7234       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7235       if(!retD)
7236         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7237       DataArrayInt *c=0,*ci=0;
7238       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7239       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7240       retD->setNodalConnectivity(cs,cis);
7241     }
7242   return ret.retn();
7243 }
7244
7245 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7246 {
7247   checkConnectivityFullyDefined();
7248   if(_types.size()!=1)
7249     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7250   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7251   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7252   if(cm.isDynamic())
7253     {
7254       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7255       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7256       throw INTERP_KERNEL::Exception(oss.str().c_str());
7257     }
7258   int nbCells=getNumberOfCells();
7259   int typi=(int)typ;
7260   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7261   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7262   int *outPtr=connOut->getPointer();
7263   const int *conn=_nodal_connec->begin();
7264   const int *connI=_nodal_connec_index->begin();
7265   nbNodesPerCell++;
7266   for(int i=0;i<nbCells;i++,connI++)
7267     {
7268       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7269         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7270       else
7271         {
7272           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 << ") !";
7273           throw INTERP_KERNEL::Exception(oss.str().c_str());
7274         }
7275     }
7276   return connOut.retn();
7277 }
7278
7279 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7280 {
7281   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7282   checkConnectivityFullyDefined();
7283   if(_types.size()!=1)
7284     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7285   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7286   if(lgth<nbCells)
7287     throw INTERP_KERNEL::Exception(msg0);
7288   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7289   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7290   int *cp(c->getPointer()),*cip(ci->getPointer());
7291   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7292   cip[0]=0;
7293   for(int i=0;i<nbCells;i++,cip++,incip++)
7294     {
7295       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7296       int delta(stop-strt);
7297       if(delta>=1)
7298         {
7299           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7300             cp=std::copy(incp+strt,incp+stop,cp);
7301           else
7302             throw INTERP_KERNEL::Exception(msg0);
7303         }
7304       else
7305         throw INTERP_KERNEL::Exception(msg0);
7306       cip[1]=cip[0]+delta;
7307     }
7308   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7309 }
7310
7311 /*!
7312  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7313  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7314  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7315  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7316  * are not used here to avoid the build of big permutation array.
7317  *
7318  * \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
7319  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7320  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7321  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7322  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7323  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7324  * \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
7325  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7326  */
7327 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7328                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7329                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7330 {
7331   std::vector<const MEDCouplingUMesh *> ms2;
7332   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7333     if(*it)
7334       {
7335         (*it)->checkConnectivityFullyDefined();
7336         ms2.push_back(*it);
7337       }
7338   if(ms2.empty())
7339     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7340   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7341   int meshDim=ms2[0]->getMeshDimension();
7342   std::vector<const MEDCouplingUMesh *> m1ssm;
7343   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7344   //
7345   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7346   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7347   int fake=0,rk=0;
7348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7349   ret1->alloc(0,1); ret2->alloc(0,1);
7350   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7351     {
7352       if(meshDim!=(*it)->getMeshDimension())
7353         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7354       if(refCoo!=(*it)->getCoords())
7355         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7356       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7357       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7358       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7359       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7360         {
7361           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7362           m1ssmSingleAuto.push_back(singleCell);
7363           m1ssmSingle.push_back(singleCell);
7364           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7365         }
7366     }
7367   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7369   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7370   for(std::size_t i=0;i<m1ssm.size();i++)
7371     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7372   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7373   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7374   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7375   return ret0.retn();
7376 }
7377
7378 /*!
7379  * This method returns a newly created DataArrayInt instance.
7380  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7381  */
7382 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7383 {
7384   checkFullyDefined();
7385   const int *conn=_nodal_connec->getConstPointer();
7386   const int *connIndex=_nodal_connec_index->getConstPointer();
7387   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7388   for(const int *w=begin;w!=end;w++)
7389     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7390       ret->pushBackSilent(*w);
7391   return ret.retn();
7392 }
7393
7394 /*!
7395  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7396  * are in [0:getNumberOfCells())
7397  */
7398 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7399 {
7400   checkFullyDefined();
7401   const int *conn=_nodal_connec->getConstPointer();
7402   const int *connI=_nodal_connec_index->getConstPointer();
7403   int nbOfCells=getNumberOfCells();
7404   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7405   int *tmp=new int[nbOfCells];
7406   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7407     {
7408       int j=0;
7409       for(const int *i=connI;i!=connI+nbOfCells;i++)
7410         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7411           tmp[std::distance(connI,i)]=j++;
7412     }
7413   DataArrayInt *ret=DataArrayInt::New();
7414   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7415   ret->copyStringInfoFrom(*da);
7416   int *retPtr=ret->getPointer();
7417   const int *daPtr=da->getConstPointer();
7418   int nbOfElems=da->getNbOfElems();
7419   for(int k=0;k<nbOfElems;k++)
7420     retPtr[k]=tmp[daPtr[k]];
7421   delete [] tmp;
7422   return ret;
7423 }
7424
7425 /*!
7426  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7427  * This method \b works \b for mesh sorted by type.
7428  * cells whose ids is in 'idsPerGeoType' array.
7429  * This method conserves coords and name of mesh.
7430  */
7431 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7432 {
7433   std::vector<int> code=getDistributionOfTypes();
7434   std::size_t nOfTypesInThis=code.size()/3;
7435   int sz=0,szOfType=0;
7436   for(std::size_t i=0;i<nOfTypesInThis;i++)
7437     {
7438       if(code[3*i]!=type)
7439         sz+=code[3*i+1];
7440       else
7441         szOfType=code[3*i+1];
7442     }
7443   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7444     if(*work<0 || *work>=szOfType)
7445       {
7446         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7447         oss << ". It should be in [0," << szOfType << ") !";
7448         throw INTERP_KERNEL::Exception(oss.str().c_str());
7449       }
7450   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7451   int *idsPtr=idsTokeep->getPointer();
7452   int offset=0;
7453   for(std::size_t i=0;i<nOfTypesInThis;i++)
7454     {
7455       if(code[3*i]!=type)
7456         for(int j=0;j<code[3*i+1];j++)
7457           *idsPtr++=offset+j;
7458       else
7459         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7460       offset+=code[3*i+1];
7461     }
7462   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7463   ret->copyTinyInfoFrom(this);
7464   return ret.retn();
7465 }
7466
7467 /*!
7468  * This method returns a vector of size 'this->getNumberOfCells()'.
7469  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7470  */
7471 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7472 {
7473   int ncell=getNumberOfCells();
7474   std::vector<bool> ret(ncell);
7475   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7476   const int *c=getNodalConnectivity()->getConstPointer();
7477   for(int i=0;i<ncell;i++)
7478     {
7479       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7480       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7481       ret[i]=cm.isQuadratic();
7482     }
7483   return ret;
7484 }
7485
7486 /*!
7487  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7488  */
7489 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7490 {
7491   if(other->getType()!=UNSTRUCTURED)
7492     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7493   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7494   return MergeUMeshes(this,otherC);
7495 }
7496
7497 /*!
7498  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7499  * computed by averaging coordinates of cell nodes, so this method is not a right
7500  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7501  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7502  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7503  *          components. The caller is to delete this array using decrRef() as it is
7504  *          no more needed.
7505  *  \throw If the coordinates array is not set.
7506  *  \throw If the nodal connectivity of cells is not defined.
7507  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7508  */
7509 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7510 {
7511   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7512   int spaceDim=getSpaceDimension();
7513   int nbOfCells=getNumberOfCells();
7514   ret->alloc(nbOfCells,spaceDim);
7515   ret->copyStringInfoFrom(*getCoords());
7516   double *ptToFill=ret->getPointer();
7517   const int *nodal=_nodal_connec->getConstPointer();
7518   const int *nodalI=_nodal_connec_index->getConstPointer();
7519   const double *coor=_coords->getConstPointer();
7520   for(int i=0;i<nbOfCells;i++)
7521     {
7522       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7523       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7524       ptToFill+=spaceDim;
7525     }
7526   return ret.retn();
7527 }
7528
7529 /*!
7530  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7531  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7532  * 
7533  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7534  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7535  * 
7536  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7537  * \throw If \a this is not fully defined (coordinates and connectivity)
7538  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7539  */
7540 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7541 {
7542   checkFullyDefined();
7543   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7544   int spaceDim=getSpaceDimension();
7545   int nbOfCells=getNumberOfCells();
7546   int nbOfNodes=getNumberOfNodes();
7547   ret->alloc(nbOfCells,spaceDim);
7548   double *ptToFill=ret->getPointer();
7549   const int *nodal=_nodal_connec->getConstPointer();
7550   const int *nodalI=_nodal_connec_index->getConstPointer();
7551   const double *coor=_coords->getConstPointer();
7552   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7553     {
7554       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7555       std::fill(ptToFill,ptToFill+spaceDim,0.);
7556       if(type!=INTERP_KERNEL::NORM_POLYHED)
7557         {
7558           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7559             {
7560               if(*conn>=0 && *conn<nbOfNodes)
7561                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7562               else
7563                 {
7564                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7565                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7566                 }
7567             }
7568           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7569           if(nbOfNodesInCell>0)
7570             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7571           else
7572             {
7573               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7574               throw INTERP_KERNEL::Exception(oss.str().c_str());
7575             }
7576         }
7577       else
7578         {
7579           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7580           s.erase(-1);
7581           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7582             {
7583               if(*it>=0 && *it<nbOfNodes)
7584                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7585               else
7586                 {
7587                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7588                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7589                 }
7590             }
7591           if(!s.empty())
7592             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7593           else
7594             {
7595               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7596               throw INTERP_KERNEL::Exception(oss.str().c_str());
7597             }
7598         }
7599     }
7600   return ret.retn();
7601 }
7602
7603 /*!
7604  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7605  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7606  * are specified via an array of cell ids. 
7607  *  \warning Validity of the specified cell ids is not checked! 
7608  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7609  *  \param [in] begin - an array of cell ids of interest.
7610  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7611  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7612  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7613  *          caller is to delete this array using decrRef() as it is no more needed. 
7614  *  \throw If the coordinates array is not set.
7615  *  \throw If the nodal connectivity of cells is not defined.
7616  *
7617  *  \if ENABLE_EXAMPLES
7618  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7619  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7620  *  \endif
7621  */
7622 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7623 {
7624   DataArrayDouble *ret=DataArrayDouble::New();
7625   int spaceDim=getSpaceDimension();
7626   int nbOfTuple=(int)std::distance(begin,end);
7627   ret->alloc(nbOfTuple,spaceDim);
7628   double *ptToFill=ret->getPointer();
7629   double *tmp=new double[spaceDim];
7630   const int *nodal=_nodal_connec->getConstPointer();
7631   const int *nodalI=_nodal_connec_index->getConstPointer();
7632   const double *coor=_coords->getConstPointer();
7633   for(const int *w=begin;w!=end;w++)
7634     {
7635       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7636       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7637       ptToFill+=spaceDim;
7638     }
7639   delete [] tmp;
7640   return ret;
7641 }
7642
7643 /*!
7644  * 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".
7645  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7646  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7647  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7648  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7649  * 
7650  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7651  * \throw If spaceDim!=3 or meshDim!=2.
7652  * \throw If connectivity of \a this is invalid.
7653  * \throw If connectivity of a cell in \a this points to an invalid node.
7654  */
7655 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7656 {
7657   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7658   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7659   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7660     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7661   ret->alloc(nbOfCells,4);
7662   double *retPtr(ret->getPointer());
7663   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7664   const double *coor(_coords->begin());
7665   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7666     {
7667       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7668       if(nodalI[1]-nodalI[0]>=3)
7669         {
7670           for(int j=0;j<3;j++)
7671             {
7672               int nodeId(nodal[nodalI[0]+1+j]);
7673               if(nodeId>=0 && nodeId<nbOfNodes)
7674                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7675               else
7676                 {
7677                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7678                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7679                 }
7680             }
7681         }
7682       else
7683         {
7684           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7685           throw INTERP_KERNEL::Exception(oss.str().c_str());
7686         }
7687       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7688       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7689     }
7690   return ret.retn();
7691 }
7692
7693 /*!
7694  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7695  * 
7696  */
7697 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7698 {
7699   if(!da)
7700     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7701   da->checkAllocated();
7702   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7703   ret->setCoords(da);
7704   int nbOfTuples=da->getNumberOfTuples();
7705   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7706   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7707   c->alloc(2*nbOfTuples,1);
7708   cI->alloc(nbOfTuples+1,1);
7709   int *cp=c->getPointer();
7710   int *cip=cI->getPointer();
7711   *cip++=0;
7712   for(int i=0;i<nbOfTuples;i++)
7713     {
7714       *cp++=INTERP_KERNEL::NORM_POINT1;
7715       *cp++=i;
7716       *cip++=2*(i+1);
7717     }
7718   ret->setConnectivity(c,cI,true);
7719   return ret.retn();
7720 }
7721 /*!
7722  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7723  * Cells and nodes of
7724  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7725  *  \param [in] mesh1 - the first mesh.
7726  *  \param [in] mesh2 - the second mesh.
7727  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7728  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7729  *          is no more needed.
7730  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7731  *  \throw If the coordinates array is not set in none of the meshes.
7732  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7733  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7734  */
7735 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7736 {
7737   std::vector<const MEDCouplingUMesh *> tmp(2);
7738   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7739   return MergeUMeshes(tmp);
7740 }
7741
7742 /*!
7743  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7744  * Cells and nodes of
7745  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7746  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7747  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7748  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7749  *          is no more needed.
7750  *  \throw If \a a.size() == 0.
7751  *  \throw If \a a[ *i* ] == NULL.
7752  *  \throw If the coordinates array is not set in none of the meshes.
7753  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7754  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7755  */
7756 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7757 {
7758   std::size_t sz=a.size();
7759   if(sz==0)
7760     return MergeUMeshesLL(a);
7761   for(std::size_t ii=0;ii<sz;ii++)
7762     if(!a[ii])
7763       {
7764         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7765         throw INTERP_KERNEL::Exception(oss.str().c_str());
7766       }
7767   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7768   std::vector< const MEDCouplingUMesh * > aa(sz);
7769   int spaceDim=-3;
7770   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7771     {
7772       const MEDCouplingUMesh *cur=a[i];
7773       const DataArrayDouble *coo=cur->getCoords();
7774       if(coo)
7775         spaceDim=coo->getNumberOfComponents();
7776     }
7777   if(spaceDim==-3)
7778     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7779   for(std::size_t i=0;i<sz;i++)
7780     {
7781       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7782       aa[i]=bb[i];
7783     }
7784   return MergeUMeshesLL(aa);
7785 }
7786
7787 /// @cond INTERNAL
7788
7789 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7790 {
7791   if(a.empty())
7792     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7793   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7794   int meshDim=(*it)->getMeshDimension();
7795   int nbOfCells=(*it)->getNumberOfCells();
7796   int meshLgth=(*it++)->getMeshLength();
7797   for(;it!=a.end();it++)
7798     {
7799       if(meshDim!=(*it)->getMeshDimension())
7800         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7801       nbOfCells+=(*it)->getNumberOfCells();
7802       meshLgth+=(*it)->getMeshLength();
7803     }
7804   std::vector<const MEDCouplingPointSet *> aps(a.size());
7805   std::copy(a.begin(),a.end(),aps.begin());
7806   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7807   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7808   ret->setCoords(pts);
7809   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7810   c->alloc(meshLgth,1);
7811   int *cPtr=c->getPointer();
7812   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7813   cI->alloc(nbOfCells+1,1);
7814   int *cIPtr=cI->getPointer();
7815   *cIPtr++=0;
7816   int offset=0;
7817   int offset2=0;
7818   for(it=a.begin();it!=a.end();it++)
7819     {
7820       int curNbOfCell=(*it)->getNumberOfCells();
7821       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7822       const int *curC=(*it)->_nodal_connec->getConstPointer();
7823       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7824       for(int j=0;j<curNbOfCell;j++)
7825         {
7826           const int *src=curC+curCI[j];
7827           *cPtr++=*src++;
7828           for(;src!=curC+curCI[j+1];src++,cPtr++)
7829             {
7830               if(*src!=-1)
7831                 *cPtr=*src+offset2;
7832               else
7833                 *cPtr=-1;
7834             }
7835         }
7836       offset+=curCI[curNbOfCell];
7837       offset2+=(*it)->getNumberOfNodes();
7838     }
7839   //
7840   ret->setConnectivity(c,cI,true);
7841   return ret.retn();
7842 }
7843
7844 /// @endcond
7845
7846 /*!
7847  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7848  * dimension and sharing the node coordinates array.
7849  * All cells of the first mesh precede all cells of the second mesh
7850  * within the result mesh. 
7851  *  \param [in] mesh1 - the first mesh.
7852  *  \param [in] mesh2 - the second mesh.
7853  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7854  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7855  *          is no more needed.
7856  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7857  *  \throw If the meshes do not share the node coordinates array.
7858  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7859  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7860  */
7861 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7862 {
7863   std::vector<const MEDCouplingUMesh *> tmp(2);
7864   tmp[0]=mesh1; tmp[1]=mesh2;
7865   return MergeUMeshesOnSameCoords(tmp);
7866 }
7867
7868 /*!
7869  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7870  * dimension and sharing the node coordinates array.
7871  * All cells of the *i*-th mesh precede all cells of the
7872  * (*i*+1)-th mesh within the result mesh.
7873  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7874  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7875  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7876  *          is no more needed.
7877  *  \throw If \a a.size() == 0.
7878  *  \throw If \a a[ *i* ] == NULL.
7879  *  \throw If the meshes do not share the node coordinates array.
7880  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7881  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7882  */
7883 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7884 {
7885   if(meshes.empty())
7886     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7887   for(std::size_t ii=0;ii<meshes.size();ii++)
7888     if(!meshes[ii])
7889       {
7890         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7891         throw INTERP_KERNEL::Exception(oss.str().c_str());
7892       }
7893   const DataArrayDouble *coords=meshes.front()->getCoords();
7894   int meshDim=meshes.front()->getMeshDimension();
7895   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7896   int meshLgth=0;
7897   int meshIndexLgth=0;
7898   for(;iter!=meshes.end();iter++)
7899     {
7900       if(coords!=(*iter)->getCoords())
7901         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7902       if(meshDim!=(*iter)->getMeshDimension())
7903         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7904       meshLgth+=(*iter)->getMeshLength();
7905       meshIndexLgth+=(*iter)->getNumberOfCells();
7906     }
7907   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7908   nodal->alloc(meshLgth,1);
7909   int *nodalPtr=nodal->getPointer();
7910   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7911   nodalIndex->alloc(meshIndexLgth+1,1);
7912   int *nodalIndexPtr=nodalIndex->getPointer();
7913   int offset=0;
7914   for(iter=meshes.begin();iter!=meshes.end();iter++)
7915     {
7916       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7917       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7918       int nbOfCells=(*iter)->getNumberOfCells();
7919       int meshLgth2=(*iter)->getMeshLength();
7920       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7921       if(iter!=meshes.begin())
7922         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7923       else
7924         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7925       offset+=meshLgth2;
7926     }
7927   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7928   ret->setName("merge");
7929   ret->setMeshDimension(meshDim);
7930   ret->setConnectivity(nodal,nodalIndex,true);
7931   ret->setCoords(coords);
7932   return ret;
7933 }
7934
7935 /*!
7936  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7937  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7938  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7939  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7940  * New" mode are returned for each input mesh.
7941  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7942  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7943  *          valid values [0,1,2], see zipConnectivityTraducer().
7944  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7945  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7946  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7947  *          no more needed.
7948  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7949  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7950  *          is no more needed.
7951  *  \throw If \a meshes.size() == 0.
7952  *  \throw If \a meshes[ *i* ] == NULL.
7953  *  \throw If the meshes do not share the node coordinates array.
7954  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7955  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7956  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7957  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7958  */
7959 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7960 {
7961   //All checks are delegated to MergeUMeshesOnSameCoords
7962   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7963   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7964   corr.resize(meshes.size());
7965   std::size_t nbOfMeshes=meshes.size();
7966   int offset=0;
7967   const int *o2nPtr=o2n->getConstPointer();
7968   for(std::size_t i=0;i<nbOfMeshes;i++)
7969     {
7970       DataArrayInt *tmp=DataArrayInt::New();
7971       int curNbOfCells=meshes[i]->getNumberOfCells();
7972       tmp->alloc(curNbOfCells,1);
7973       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7974       offset+=curNbOfCells;
7975       tmp->setName(meshes[i]->getName());
7976       corr[i]=tmp;
7977     }
7978   return ret.retn();
7979 }
7980
7981 /*!
7982  * Makes all given meshes share the nodal connectivity array. The common connectivity
7983  * array is created by concatenating the connectivity arrays of all given meshes. All
7984  * the given meshes must be of the same space dimension but dimension of cells **can
7985  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7986  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7987  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7988  *  \param [in,out] meshes - a vector of meshes to update.
7989  *  \throw If any of \a meshes is NULL.
7990  *  \throw If the coordinates array is not set in any of \a meshes.
7991  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7992  *  \throw If \a meshes are of different space dimension.
7993  */
7994 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7995 {
7996   std::size_t sz=meshes.size();
7997   if(sz==0 || sz==1)
7998     return;
7999   std::vector< const DataArrayDouble * > coords(meshes.size());
8000   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8001   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8002     {
8003       if((*it))
8004         {
8005           (*it)->checkConnectivityFullyDefined();
8006           const DataArrayDouble *coo=(*it)->getCoords();
8007           if(coo)
8008             *it2=coo;
8009           else
8010             {
8011               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8012               oss << " has no coordinate array defined !";
8013               throw INTERP_KERNEL::Exception(oss.str().c_str());
8014             }
8015         }
8016       else
8017         {
8018           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8019           oss << " is null !";
8020           throw INTERP_KERNEL::Exception(oss.str().c_str());
8021         }
8022     }
8023   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8024   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8025   int offset=(*it)->getNumberOfNodes();
8026   (*it++)->setCoords(res);
8027   for(;it!=meshes.end();it++)
8028     {
8029       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8030       (*it)->setCoords(res);
8031       (*it)->shiftNodeNumbersInConn(offset);
8032       offset+=oldNumberOfNodes;
8033     }
8034 }
8035
8036 /*!
8037  * Merges nodes coincident with a given precision within all given meshes that share
8038  * the nodal connectivity array. The given meshes **can be of different** mesh
8039  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8040  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8041  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8042  *  \param [in,out] meshes - a vector of meshes to update.
8043  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8044  *  \throw If any of \a meshes is NULL.
8045  *  \throw If the \a meshes do not share the same node coordinates array.
8046  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8047  */
8048 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8049 {
8050   if(meshes.empty())
8051     return ;
8052   std::set<const DataArrayDouble *> s;
8053   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8054     {
8055       if(*it)
8056         s.insert((*it)->getCoords());
8057       else
8058         {
8059           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 !";
8060           throw INTERP_KERNEL::Exception(oss.str().c_str());
8061         }
8062     }
8063   if(s.size()!=1)
8064     {
8065       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 !";
8066       throw INTERP_KERNEL::Exception(oss.str().c_str());
8067     }
8068   const DataArrayDouble *coo=*(s.begin());
8069   if(!coo)
8070     return;
8071   //
8072   DataArrayInt *comm,*commI;
8073   coo->findCommonTuples(eps,-1,comm,commI);
8074   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8075   int oldNbOfNodes=coo->getNumberOfTuples();
8076   int newNbOfNodes;
8077   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8078   if(oldNbOfNodes==newNbOfNodes)
8079     return ;
8080   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8081   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8082     {
8083       (*it)->renumberNodesInConn(o2n->getConstPointer());
8084       (*it)->setCoords(newCoords);
8085     } 
8086 }
8087
8088 /*!
8089  * 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.
8090  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8091  * \param isQuad specifies the policy of connectivity.
8092  * @ret in/out parameter in which the result will be append
8093  */
8094 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8095 {
8096   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8097   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8098   ret.push_back(cm.getExtrudedType());
8099   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8100   switch(flatType)
8101   {
8102     case INTERP_KERNEL::NORM_POINT1:
8103       {
8104         ret.push_back(connBg[1]);
8105         ret.push_back(connBg[1]+nbOfNodesPerLev);
8106         break;
8107       }
8108     case INTERP_KERNEL::NORM_SEG2:
8109       {
8110         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8111         ret.insert(ret.end(),conn,conn+4);
8112         break;
8113       }
8114     case INTERP_KERNEL::NORM_SEG3:
8115       {
8116         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8117         ret.insert(ret.end(),conn,conn+8);
8118         break;
8119       }
8120     case INTERP_KERNEL::NORM_QUAD4:
8121       {
8122         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8123         ret.insert(ret.end(),conn,conn+8);
8124         break;
8125       }
8126     case INTERP_KERNEL::NORM_TRI3:
8127       {
8128         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8129         ret.insert(ret.end(),conn,conn+6);
8130         break;
8131       }
8132     case INTERP_KERNEL::NORM_TRI6:
8133       {
8134         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,
8135           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8136         ret.insert(ret.end(),conn,conn+15);
8137         break;
8138       }
8139     case INTERP_KERNEL::NORM_QUAD8:
8140       {
8141         int conn[20]={
8142           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8143           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8144           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8145         };
8146         ret.insert(ret.end(),conn,conn+20);
8147         break;
8148       }
8149     case INTERP_KERNEL::NORM_POLYGON:
8150       {
8151         std::back_insert_iterator< std::vector<int> > ii(ret);
8152         std::copy(connBg+1,connEnd,ii);
8153         *ii++=-1;
8154         std::reverse_iterator<const int *> rConnBg(connEnd);
8155         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8156         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8157         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8158         for(std::size_t i=0;i<nbOfRadFaces;i++)
8159           {
8160             *ii++=-1;
8161             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8162             std::copy(conn,conn+4,ii);
8163           }
8164         break;
8165       }
8166     default:
8167       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8168   }
8169 }
8170
8171 /*!
8172  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8173  */
8174 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8175 {
8176   std::size_t i, ip1;
8177   double v[3]={0.,0.,0.};
8178   std::size_t sz=std::distance(begin,end);
8179   if(isQuadratic)
8180     sz/=2;
8181   for(i=0;i<sz;i++)
8182     {
8183       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];
8184       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8185       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8186     }
8187   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8188
8189   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8190   // SEG3 forming a circle):
8191   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8192     {
8193       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8194       for(std::size_t j=0;j<sz;j++)
8195         {
8196           if (j%2)  // current point i is quadratic, next point i+1 is standard
8197             {
8198               i = sz+j;
8199               ip1 = (j+1)%sz; // ip1 = "i+1"
8200             }
8201           else      // current point i is standard, next point i+1 is quadratic
8202             {
8203               i = j;
8204               ip1 = j+sz;
8205             }
8206           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8207           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8208           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8209         }
8210       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8211     }
8212   return (ret>0.);
8213 }
8214
8215 /*!
8216  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8217  */
8218 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8219 {
8220   std::vector<std::pair<int,int> > edges;
8221   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8222   const int *bgFace=begin;
8223   for(std::size_t i=0;i<nbOfFaces;i++)
8224     {
8225       const int *endFace=std::find(bgFace+1,end,-1);
8226       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8227       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8228         {
8229           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8230           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8231             return false;
8232           edges.push_back(p1);
8233         }
8234       bgFace=endFace+1;
8235     }
8236   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8237 }
8238
8239 /*!
8240  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8241  */
8242 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8243 {
8244   double vec0[3],vec1[3];
8245   std::size_t sz=std::distance(begin,end);
8246   if(sz%2!=0)
8247     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8248   int nbOfNodes=(int)sz/2;
8249   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8250   const double *pt0=coords+3*begin[0];
8251   const double *pt1=coords+3*begin[nbOfNodes];
8252   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8253   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8254 }
8255
8256 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8257 {
8258   std::size_t sz=std::distance(begin,end);
8259   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8260   std::size_t nbOfNodes(sz/2);
8261   std::copy(begin,end,(int *)tmp);
8262   for(std::size_t j=1;j<nbOfNodes;j++)
8263     {
8264       begin[j]=tmp[nbOfNodes-j];
8265       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8266     }
8267 }
8268
8269 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8270 {
8271   std::size_t sz=std::distance(begin,end);
8272   if(sz!=4)
8273     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8274   double vec0[3],vec1[3];
8275   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8276   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]; 
8277   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;
8278 }
8279
8280 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8281 {
8282   std::size_t sz=std::distance(begin,end);
8283   if(sz!=5)
8284     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8285   double vec0[3];
8286   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8287   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8288   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8289 }
8290
8291 /*!
8292  * 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 ) 
8293  * 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
8294  * a 2D space.
8295  *
8296  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8297  * \param [in] coords the coordinates with nb of components exactly equal to 3
8298  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8299  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8300  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8301  */
8302 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8303 {
8304   int nbFaces=std::count(begin+1,end,-1)+1;
8305   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8306   double *vPtr=v->getPointer();
8307   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8308   double *pPtr=p->getPointer();
8309   const int *stFaceConn=begin+1;
8310   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8311     {
8312       const int *endFaceConn=std::find(stFaceConn,end,-1);
8313       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8314       stFaceConn=endFaceConn+1;
8315     }
8316   pPtr=p->getPointer(); vPtr=v->getPointer();
8317   DataArrayInt *comm1=0,*commI1=0;
8318   v->findCommonTuples(eps,-1,comm1,commI1);
8319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8320   const int *comm1Ptr=comm1->getConstPointer();
8321   const int *commI1Ptr=commI1->getConstPointer();
8322   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8323   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8324   //
8325   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8326   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8327   mm->finishInsertingCells();
8328   //
8329   for(int i=0;i<nbOfGrps1;i++)
8330     {
8331       int vecId=comm1Ptr[commI1Ptr[i]];
8332       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8333       DataArrayInt *comm2=0,*commI2=0;
8334       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8335       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8336       const int *comm2Ptr=comm2->getConstPointer();
8337       const int *commI2Ptr=commI2->getConstPointer();
8338       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8339       for(int j=0;j<nbOfGrps2;j++)
8340         {
8341           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8342             {
8343               res->insertAtTheEnd(begin,end);
8344               res->pushBackSilent(-1);
8345             }
8346           else
8347             {
8348               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8349               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8350               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8351               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8352               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8353               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8354               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8355               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8356               const int *idsNodePtr=idsNode->getConstPointer();
8357               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];
8358               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8359               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8360               if(std::abs(norm)>eps)
8361                 {
8362                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8363                   mm3->rotate(center,vec,angle);
8364                 }
8365               mm3->changeSpaceDimension(2);
8366               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8367               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8368               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8369               int nbOfCells=mm4->getNumberOfCells();
8370               for(int k=0;k<nbOfCells;k++)
8371                 {
8372                   int l=0;
8373                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8374                     res->pushBackSilent(idsNodePtr[*work]);
8375                   res->pushBackSilent(-1);
8376                 }
8377             }
8378         }
8379     }
8380   res->popBackSilent();
8381 }
8382
8383 /*!
8384  * 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
8385  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8386  * 
8387  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8388  * \param [in] coords coordinates expected to have 3 components.
8389  * \param [in] begin start of the nodal connectivity of the face.
8390  * \param [in] end end of the nodal connectivity (excluded) of the face.
8391  * \param [out] v the normalized vector of size 3
8392  * \param [out] p the pos of plane
8393  */
8394 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8395 {
8396   std::size_t nbPoints=std::distance(begin,end);
8397   if(nbPoints<3)
8398     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8399   double vec[3]={0.,0.,0.};
8400   std::size_t j=0;
8401   bool refFound=false;
8402   for(;j<nbPoints-1 && !refFound;j++)
8403     {
8404       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8405       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8406       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8407       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8408       if(norm>eps)
8409         {
8410           refFound=true;
8411           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8412         }
8413     }
8414   for(std::size_t i=j;i<nbPoints-1;i++)
8415     {
8416       double curVec[3];
8417       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8418       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8419       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8420       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8421       if(norm<eps)
8422         continue;
8423       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8424       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];
8425       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8426       if(norm>eps)
8427         {
8428           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8429           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8430           return ;
8431         }
8432     }
8433   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8434 }
8435
8436 /*!
8437  * This method tries to obtain a well oriented polyhedron.
8438  * If the algorithm fails, an exception will be thrown.
8439  */
8440 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8441 {
8442   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8443   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8444   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8445   isPerm[0]=true;
8446   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8447   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8448   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8449   //
8450   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8451     {
8452       bgFace=begin;
8453       std::size_t smthChanged=0;
8454       for(std::size_t i=0;i<nbOfFaces;i++)
8455         {
8456           endFace=std::find(bgFace+1,end,-1);
8457           nbOfEdgesInFace=std::distance(bgFace,endFace);
8458           if(!isPerm[i])
8459             {
8460               bool b;
8461               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8462                 {
8463                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8464                   std::pair<int,int> p2(p1.second,p1.first);
8465                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8466                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8467                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8468                 }
8469               if(isPerm[i])
8470                 { 
8471                   if(!b)
8472                     std::reverse(bgFace+1,endFace);
8473                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8474                     {
8475                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8476                       std::pair<int,int> p2(p1.second,p1.first);
8477                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8478                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8479                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8480                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8481                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8482                       if(it!=edgesOK.end())
8483                         {
8484                           edgesOK.erase(it);
8485                           edgesFinished.push_back(p1);
8486                         }
8487                       else
8488                         edgesOK.push_back(p1);
8489                     }
8490                 }
8491             }
8492           bgFace=endFace+1;
8493         }
8494       if(smthChanged==0)
8495         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8496     }
8497   if(!edgesOK.empty())
8498     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8499   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8500     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8501       bgFace=begin;
8502       for(std::size_t i=0;i<nbOfFaces;i++)
8503         {
8504           endFace=std::find(bgFace+1,end,-1);
8505           std::reverse(bgFace+1,endFace);
8506           bgFace=endFace+1;
8507         }
8508     }
8509 }
8510
8511 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8512 {
8513   int nbOfNodesExpected(skin->getNumberOfNodes());
8514   const int *n2oPtr(n2o->getConstPointer());
8515   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8516   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8517   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8518   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8519   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8520   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8521   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8522   if(nbOfNodesExpected<1)
8523     return ret.retn();
8524   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8525   *work++=n2oPtr[prevNode];
8526   for(int i=1;i<nbOfNodesExpected;i++)
8527     {
8528       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8529         {
8530           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8531           conn.erase(prevNode);
8532           if(conn.size()==1)
8533             {
8534               int curNode(*(conn.begin()));
8535               *work++=n2oPtr[curNode];
8536               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8537               shar.erase(prevCell);
8538               if(shar.size()==1)
8539                 {
8540                   prevCell=*(shar.begin());
8541                   prevNode=curNode;
8542                 }
8543               else
8544                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8545             }
8546           else
8547             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8548         }
8549       else
8550         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8551     }
8552   return ret.retn();
8553 }
8554
8555 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8556 {
8557   int nbOfNodesExpected(skin->getNumberOfNodes());
8558   int nbOfTurn(nbOfNodesExpected/2);
8559   const int *n2oPtr(n2o->getConstPointer());
8560   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8561   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8562   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8563   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8564   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8565   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8566   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8567   if(nbOfNodesExpected<1)
8568     return ret.retn();
8569   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8570   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8571   for(int i=1;i<nbOfTurn;i++)
8572     {
8573       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8574         {
8575           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8576           conn.erase(prevNode);
8577           if(conn.size()==1)
8578             {
8579               int curNode(*(conn.begin()));
8580               *work=n2oPtr[curNode];
8581               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8582               shar.erase(prevCell);
8583               if(shar.size()==1)
8584                 {
8585                   int curCell(*(shar.begin()));
8586                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8587                   prevCell=curCell;
8588                   prevNode=curNode;
8589                   work++;
8590                 }
8591               else
8592                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8593             }
8594           else
8595             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8596         }
8597       else
8598         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8599     }
8600   return ret.retn();
8601 }
8602
8603 /*!
8604  * This method makes the assumption spacedimension == meshdimension == 2.
8605  * This method works only for linear cells.
8606  * 
8607  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8608  */
8609 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8610 {
8611   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8612     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8613   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8614   int oldNbOfNodes(skin->getNumberOfNodes());
8615   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8616   int nbOfNodesExpected(skin->getNumberOfNodes());
8617   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8618   int nbCells(skin->getNumberOfCells());
8619   if(nbCells==nbOfNodesExpected)
8620     return buildUnionOf2DMeshLinear(skin,n2o);
8621   else if(2*nbCells==nbOfNodesExpected)
8622     return buildUnionOf2DMeshQuadratic(skin,n2o);
8623   else
8624     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8625 }
8626
8627 /*!
8628  * This method makes the assumption spacedimension == meshdimension == 3.
8629  * This method works only for linear cells.
8630  * 
8631  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8632  */
8633 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8634 {
8635   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8636     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8637   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8638   const int *conn=m->getNodalConnectivity()->getConstPointer();
8639   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8640   int nbOfCells=m->getNumberOfCells();
8641   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8642   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8643   if(nbOfCells<1)
8644     return ret.retn();
8645   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8646   for(int i=1;i<nbOfCells;i++)
8647     {
8648       *work++=-1;
8649       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8650     }
8651   return ret.retn();
8652 }
8653
8654 /*!
8655  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8656  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8657  */
8658 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8659 {
8660   double *w=zipFrmt;
8661   if(spaceDim==3)
8662     for(int i=0;i<nbOfNodesInCell;i++)
8663       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8664   else if(spaceDim==2)
8665     {
8666       for(int i=0;i<nbOfNodesInCell;i++)
8667         {
8668           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8669           *w++=0.;
8670         }
8671     }
8672   else
8673     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8674 }
8675
8676 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8677 {
8678   int nbOfCells=getNumberOfCells();
8679   if(nbOfCells<=0)
8680     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8681   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};
8682   ofs << "  <" << getVTKDataSetType() << ">\n";
8683   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8684   ofs << "      <PointData>\n" << pointData << std::endl;
8685   ofs << "      </PointData>\n";
8686   ofs << "      <CellData>\n" << cellData << std::endl;
8687   ofs << "      </CellData>\n";
8688   ofs << "      <Points>\n";
8689   if(getSpaceDimension()==3)
8690     _coords->writeVTK(ofs,8,"Points",byteData);
8691   else
8692     {
8693       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8694       coo->writeVTK(ofs,8,"Points",byteData);
8695     }
8696   ofs << "      </Points>\n";
8697   ofs << "      <Cells>\n";
8698   const int *cPtr=_nodal_connec->getConstPointer();
8699   const int *cIPtr=_nodal_connec_index->getConstPointer();
8700   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8701   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8702   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8703   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8704   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8705   int szFaceOffsets=0,szConn=0;
8706   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8707     {
8708       *w2=cPtr[cIPtr[i]];
8709       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8710         {
8711           *w1=-1;
8712           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8713           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8714         }
8715       else
8716         {
8717           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8718           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8719           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8720           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8721           w4=std::copy(c.begin(),c.end(),w4);
8722         }
8723     }
8724   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8725   types->writeVTK(ofs,8,"UInt8","types",byteData);
8726   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8727   if(szFaceOffsets!=0)
8728     {//presence of Polyhedra
8729       connectivity->reAlloc(szConn);
8730       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8731       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8732       w1=faces->getPointer();
8733       for(int i=0;i<nbOfCells;i++)
8734         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8735           {
8736             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8737             *w1++=nbFaces;
8738             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8739             for(int j=0;j<nbFaces;j++)
8740               {
8741                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8742                 *w1++=(int)std::distance(w6,w5);
8743                 w1=std::copy(w6,w5,w1);
8744                 w6=w5+1;
8745               }
8746           }
8747       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8748     }
8749   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8750   ofs << "      </Cells>\n";
8751   ofs << "    </Piece>\n";
8752   ofs << "  </" << getVTKDataSetType() << ">\n";
8753 }
8754
8755 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8756 {
8757   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8758   if(_mesh_dim==-2)
8759     { stream << " Not set !"; return ; }
8760   stream << " Mesh dimension : " << _mesh_dim << ".";
8761   if(_mesh_dim==-1)
8762     return ;
8763   if(!_coords)
8764     { stream << " No coordinates set !"; return ; }
8765   if(!_coords->isAllocated())
8766     { stream << " Coordinates set but not allocated !"; return ; }
8767   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8768   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8769   if(!_nodal_connec_index)
8770     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8771   if(!_nodal_connec_index->isAllocated())
8772     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8773   int lgth=_nodal_connec_index->getNumberOfTuples();
8774   int cpt=_nodal_connec_index->getNumberOfComponents();
8775   if(cpt!=1 || lgth<1)
8776     return ;
8777   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8778 }
8779
8780 std::string MEDCouplingUMesh::getVTKDataSetType() const
8781 {
8782   return std::string("UnstructuredGrid");
8783 }
8784
8785 std::string MEDCouplingUMesh::getVTKFileExtension() const
8786 {
8787   return std::string("vtu");
8788 }
8789
8790 /*!
8791  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8792  * returns a result mesh constituted by polygons.
8793  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8794  * all nodes from m2.
8795  * The meshes should be in 2D space. In
8796  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8797  * meshes.
8798  *  \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
8799  *                      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)
8800  *  \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
8801  *                      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)
8802  *  \param [in] eps - precision used to detect coincident mesh entities.
8803  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8804  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8805  *         this array using decrRef() as it is no more needed.
8806  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8807  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8808  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8809  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8810  *         it is no more needed.  
8811  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8812  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8813  *         is no more needed.  
8814  *  \throw If the coordinates array is not set in any of the meshes.
8815  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8816  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8817  *
8818  *  \sa conformize2D, mergeNodes
8819  */
8820 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8821                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8822 {
8823   if(!m1 || !m2)
8824     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8825   m1->checkFullyDefined();
8826   m2->checkFullyDefined();
8827   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8828     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8829
8830   // Step 1: compute all edge intersections (new nodes)
8831   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8832   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8833   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8834   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8835   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8836                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8837                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8838   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8839   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8840   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8841
8842   // Step 2: re-order newly created nodes according to the ordering found in m2
8843   std::vector< std::vector<int> > intersectEdge2;
8844   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8845   subDiv2.clear(); dd5=0; dd6=0;
8846
8847   // Step 3:
8848   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8849   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8850   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8851                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8852
8853   // Step 4: Prepare final result:
8854   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8855   addCooDa->alloc((int)(addCoo.size())/2,2);
8856   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8857   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8858   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8859   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8860   std::vector<const DataArrayDouble *> coordss(4);
8861   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8862   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8863   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8864   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8866   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8867   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8868   ret->setConnectivity(conn,connI,true);
8869   ret->setCoords(coo);
8870   cellNb1=c1.retn(); cellNb2=c2.retn();
8871   return ret.retn();
8872 }
8873
8874 /// @cond INTERNAL
8875
8876 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8877 {
8878   if(candidates.empty())
8879     return false;
8880   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8881     {
8882       const std::vector<int>& pool(intersectEdge1[*it]);
8883       int tmp[2]; tmp[0]=start; tmp[1]=stop;
8884       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8885         {
8886           retVal=*it+1;
8887           return true;
8888         }
8889       tmp[0]=stop; tmp[1]=start;
8890       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8891         {
8892           retVal=-*it-1;
8893           return true;
8894         }
8895     }
8896   return false;
8897 }
8898
8899 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,
8900                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8901 {
8902   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8903   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8904   int nCells(mesh1D->getNumberOfCells());
8905   if(nCells!=(int)intersectEdge2.size())
8906     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8907   const DataArrayDouble *coo2(mesh1D->getCoords());
8908   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8909   const double *coo2Ptr(coo2->begin());
8910   int offset1(coords1->getNumberOfTuples());
8911   int offset2(offset1+coo2->getNumberOfTuples());
8912   int offset3(offset2+addCoo.size()/2);
8913   std::vector<double> addCooQuad;
8914   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8915   int tmp[4],cicnt(0),kk(0);
8916   for(int i=0;i<nCells;i++)
8917     {
8918       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8919       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8920       const std::vector<int>& subEdges(intersectEdge2[i]);
8921       int nbSubEdge(subEdges.size()/2);
8922       for(int j=0;j<nbSubEdge;j++,kk++)
8923         {
8924           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));
8925           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8926           INTERP_KERNEL::Edge *e2Ptr(e2);
8927           std::map<int,int>::const_iterator itm;
8928           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8929             {
8930               tmp[0]=INTERP_KERNEL::NORM_SEG3;
8931               itm=mergedNodes.find(subEdges[2*j]);
8932               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8933               itm=mergedNodes.find(subEdges[2*j+1]);
8934               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8935               tmp[3]=offset3+(int)addCooQuad.size()/2;
8936               double tmp2[2];
8937               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8938               cicnt+=4;
8939               cOut->insertAtTheEnd(tmp,tmp+4);
8940               ciOut->pushBackSilent(cicnt);
8941             }
8942           else
8943             {
8944               tmp[0]=INTERP_KERNEL::NORM_SEG2;
8945               itm=mergedNodes.find(subEdges[2*j]);
8946               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8947               itm=mergedNodes.find(subEdges[2*j+1]);
8948               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8949               cicnt+=3;
8950               cOut->insertAtTheEnd(tmp,tmp+3);
8951               ciOut->pushBackSilent(cicnt);
8952             }
8953           int tmp00;
8954           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8955             {
8956               idsInRetColinear->pushBackSilent(kk);
8957               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8958             }
8959         }
8960       e->decrRef();
8961     }
8962   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8963   ret->setConnectivity(cOut,ciOut,true);
8964   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8965   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8966   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8967   std::vector<const DataArrayDouble *> coordss(4);
8968   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8969   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8970   ret->setCoords(arr);
8971   return ret.retn();
8972 }
8973
8974 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8975 {
8976   std::vector<int> allEdges;
8977   for(const int *it2(descBg);it2!=descEnd;it2++)
8978     {
8979       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
8980       if(*it2>0)
8981         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8982       else
8983         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8984     }
8985   std::size_t nb(allEdges.size());
8986   if(nb%2!=0)
8987     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
8988   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8989   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8990   ret->setCoords(coords);
8991   ret->allocateCells(1);
8992   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
8993   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8994     connOut[kk]=allEdges[2*kk];
8995   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
8996   return ret.retn();
8997 }
8998
8999 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9000 {
9001   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9002   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9003   std::size_t ii(0);
9004   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9005   if(sz!=std::distance(descBg,descEnd))
9006     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9007   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9008   std::vector<int> allEdges,centers;
9009   const double *coordsPtr(coords->begin());
9010   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9011   int offset(coords->getNumberOfTuples());
9012   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9013     {
9014       INTERP_KERNEL::NormalizedCellType typeOfSon;
9015       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9016       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9017       if(*it2>0)
9018         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9019       else
9020         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9021       if(edge1.size()==2)
9022         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9023       else
9024         {//the current edge has been subsplit -> create corresponding centers.
9025           std::size_t nbOfCentersToAppend(edge1.size()/2);
9026           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9027           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9028           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9029           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9030             {
9031               double tmpp[2];
9032               const double *aa(coordsPtr+2*(*it3++));
9033               const double *bb(coordsPtr+2*(*it3++));
9034               ee->getMiddleOfPoints(aa,bb,tmpp);
9035               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9036               centers.push_back(offset+k);
9037             }
9038         }
9039     }
9040   std::size_t nb(allEdges.size());
9041   if(nb%2!=0)
9042     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9043   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9044   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9045   if(addCoo->empty())
9046     ret->setCoords(coords);
9047   else
9048     {
9049       addCoo->rearrange(2);
9050       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9051       ret->setCoords(addCoo);
9052     }
9053   ret->allocateCells(1);
9054   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9055   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9056     connOut[kk]=allEdges[2*kk];
9057   connOut.insert(connOut.end(),centers.begin(),centers.end());
9058   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9059   return ret.retn();
9060 }
9061
9062 /*!
9063  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9064  * of those edges.
9065  *
9066  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9067  */
9068 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9069 {
9070   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9071   if(!cm.isQuadratic())
9072     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9073   else
9074     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9075 }
9076
9077 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9078 {
9079   bool isQuad(false);
9080   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9081     {
9082       const INTERP_KERNEL::Edge *ee(*it);
9083       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9084         isQuad=true;
9085     }
9086   if(!isQuad)
9087     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9088   else
9089     {
9090       const double *coo(mesh2D->getCoords()->begin());
9091       std::size_t sz(conn.size());
9092       std::vector<double> addCoo;
9093       std::vector<int> conn2(conn);
9094       int offset(mesh2D->getNumberOfNodes());
9095       for(std::size_t i=0;i<sz;i++)
9096         {
9097           double tmp[2];
9098           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9099           addCoo.insert(addCoo.end(),tmp,tmp+2);
9100           conn2.push_back(offset+(int)i);
9101         }
9102       mesh2D->getCoords()->rearrange(1);
9103       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9104       mesh2D->getCoords()->rearrange(2);
9105       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9106     }
9107 }
9108
9109 /*!
9110  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9111  *
9112  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9113  * a set of edges defined in \a splitMesh1D.
9114  */
9115 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9116                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9117 {
9118   std::size_t nb(edge1Bis.size()/2);
9119   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9120   int iEnd(splitMesh1D->getNumberOfCells());
9121   if(iEnd==0)
9122     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9123   std::size_t ii,jj;
9124   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9125   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9126   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9127   //
9128   if(jj==nb)
9129     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9130       out0.resize(1); out1.resize(1);
9131       std::vector<int>& connOut(out0[0]);
9132       connOut.resize(nbOfEdgesOf2DCellSplit);
9133       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9134       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9135       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9136         {
9137           connOut[kk]=edge1Bis[2*kk];
9138           edgesPtr[kk]=edge1BisPtr[2*kk];
9139         }
9140     }
9141   else
9142     {
9143       // [i,iEnd[ contains the
9144       out0.resize(2); out1.resize(2);
9145       std::vector<int>& connOutLeft(out0[0]);
9146       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9147       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9148       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9149       for(std::size_t k=ii;k<jj+1;k++)
9150         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9151       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9152       for(int ik=0;ik<iEnd;ik++)
9153         {
9154           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9155           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9156           ees[ik]=ee;
9157         }
9158       for(int ik=iEnd-1;ik>=0;ik--)
9159         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9160       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9161         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9162       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9163       for(int ik=0;ik<iEnd;ik++)
9164         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9165       eright.insert(eright.end(),ees.begin(),ees.end());
9166     }
9167 }
9168
9169 /// @endcond
9170
9171 /// @cond INTERNAL
9172
9173 struct CellInfo
9174 {
9175 public:
9176   CellInfo() { }
9177   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9178 public:
9179   std::vector<int> _edges;
9180   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9181 };
9182
9183 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9184 {
9185   std::size_t nbe(edges.size());
9186   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9187   for(std::size_t i=0;i<nbe;i++)
9188     {
9189       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9190       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9191     }
9192   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9193   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9194   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9195 }
9196
9197 class EdgeInfo
9198 {
9199 public:
9200   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9201   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9202   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9203   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9204   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9205 private:
9206   int _istart;
9207   int _iend;
9208   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9209   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9210   int _left;
9211   int _right;
9212 };
9213
9214 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9215 {
9216   const MEDCouplingUMesh *mesh(_mesh);
9217   if(mesh)
9218     return ;
9219   if(_right<pos)
9220     return ;
9221   if(_left>pos)
9222     { _left++; _right++; return ; }
9223   if(_right==pos)
9224     {
9225       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9226       if((isLeft && isRight) || (!isLeft && !isRight))
9227         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9228       if(isLeft)
9229         return ;
9230       if(isRight)
9231         {
9232           _right++;
9233           return ;
9234         }
9235     }
9236   if(_left==pos)
9237     {
9238       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9239       if((isLeft && isRight) || (!isLeft && !isRight))
9240         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9241       if(isLeft)
9242         {
9243           _right++;
9244           return ;
9245         }
9246       if(isRight)
9247         {
9248           _left++;
9249           _right++;
9250           return ;
9251         }
9252     }
9253 }
9254
9255 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9256 {
9257   const MEDCouplingUMesh *mesh(_mesh);
9258   if(!mesh)
9259     {
9260       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9261     }
9262   else
9263     {// not fully splitting cell case
9264       if(mesh2D->getNumberOfCells()==1)
9265         {//little optimization. 1 cell no need to find in which cell mesh is !
9266           neighbors[0]=offset; neighbors[1]=offset;
9267           return;
9268         }
9269       else
9270         {
9271           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9272           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9273           if(cellId==-1)
9274             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9275           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9276         }
9277     }
9278 }
9279
9280 class VectorOfCellInfo
9281 {
9282 public:
9283   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9284   std::size_t size() const { return _pool.size(); }
9285   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9286   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);
9287   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9288   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9289   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9290   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9291 private:
9292   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9293   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9294   const CellInfo& get(int pos) const;
9295   CellInfo& get(int pos);
9296 private:
9297   std::vector<CellInfo> _pool;
9298   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9299   std::vector<EdgeInfo> _edge_info;
9300 };
9301
9302 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9303 {
9304   _pool[0]._edges=edges;
9305   _pool[0]._edges_ptr=edgesPtr;
9306 }
9307
9308 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9309 {
9310   if(_pool.empty())
9311     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9312   if(_pool.size()==1)
9313     return 0;
9314   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9315   if(!zeMesh)
9316     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9317   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9318   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9319 }
9320
9321 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)
9322 {
9323   get(pos);//to check pos
9324   bool isFast(pos==0 && _pool.size()==1);
9325   std::size_t sz(edges.size());
9326   // dealing with edges
9327   if(sz==1)
9328     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9329   else
9330     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9331   //
9332   std::vector<CellInfo> pool(_pool.size()-1+sz);
9333   for(int i=0;i<pos;i++)
9334     pool[i]=_pool[i];
9335   for(std::size_t j=0;j<sz;j++)
9336     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9337   for(int i=pos+1;i<(int)_pool.size();i++)
9338     pool[i+sz-1]=_pool[i];
9339   _pool=pool;
9340   //
9341   if(sz==2)
9342     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9343   //
9344   if(isFast)
9345     {
9346       _ze_mesh=mesh;
9347       return ;
9348     }
9349   //
9350   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9351   if(pos>0)
9352     {
9353       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9354       ms.push_back(elt);
9355     }
9356   ms.push_back(mesh);
9357   if(pos<_ze_mesh->getNumberOfCells()-1)
9358   {
9359     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9360     ms.push_back(elt);
9361   }
9362   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9363   for(std::size_t j=0;j<ms2.size();j++)
9364     ms2[j]=ms[j];
9365   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9366 }
9367
9368 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9369 {
9370   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9371 }
9372
9373 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9374 {
9375   if(pos<0)
9376     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9377   int ret(0);
9378   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9379     {
9380       if((*it).isInMyRange(pos))
9381         return ret;
9382     }
9383   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9384 }
9385
9386 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9387 {
9388   get(pos);//to check;
9389   if(_edge_info.empty())
9390     return ;
9391   std::size_t sz(_edge_info.size()-1);
9392   for(std::size_t i=0;i<sz;i++)
9393     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9394 }
9395
9396 const CellInfo& VectorOfCellInfo::get(int pos) const
9397 {
9398   if(pos<0 || pos>=(int)_pool.size())
9399     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9400   return _pool[pos];
9401 }
9402
9403 CellInfo& VectorOfCellInfo::get(int pos)
9404 {
9405   if(pos<0 || pos>=(int)_pool.size())
9406     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9407   return _pool[pos];
9408 }
9409
9410 /*!
9411  * Given :
9412  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9413  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9414  *
9415  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9416  *
9417  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9418  *
9419  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9420  */
9421 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9422                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9423 {
9424   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9425   if(nbCellsInSplitMesh1D==0)
9426     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9427   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9428   std::size_t nb(allEdges.size()),jj;
9429   if(nb%2!=0)
9430     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9431   std::vector<int> edge1Bis(nb*2);
9432   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9433   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9434   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9435   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9436   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9437   //
9438   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9439   int *idsLeftRightPtr(idsLeftRight->getPointer());
9440   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9441   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9442     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9443       int iEnd(iStart);
9444       for(;iEnd<nbCellsInSplitMesh1D;)
9445         {
9446           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9447           if(jj!=nb)
9448             break;
9449           else
9450             iEnd++;
9451         }
9452       if(iEnd<nbCellsInSplitMesh1D)
9453         iEnd++;
9454       //
9455       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9456       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9457       //
9458       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9459       retTmp->setCoords(splitMesh1D->getCoords());
9460       retTmp->allocateCells();
9461
9462       std::vector< std::vector<int> > out0;
9463       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9464
9465       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9466       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9467         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9468       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9469       //
9470       iStart=iEnd;
9471     }
9472   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9473     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9474   return pool.getZeMesh().retn();
9475 }
9476
9477 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9478                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9479                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9480 {
9481   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9482   //
9483   std::vector<int> allEdges;
9484   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9485   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9486     {
9487       int edgeId(std::abs(*it)-1);
9488       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9489       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9490       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9491       if(*it>0)
9492         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9493       else
9494         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9495       std::size_t sz(edge1.size());
9496       for(std::size_t cnt=0;cnt<sz;cnt++)
9497         allEdgesPtr.push_back(ee);
9498     }
9499   //
9500   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9501 }
9502
9503 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9504 {
9505   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9506     {//easy case comparison not
9507       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9508     }
9509   else if(typ1.isQuadratic() && typ2.isQuadratic())
9510     {
9511       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9512       if(!status0)
9513         return false;
9514       if(conn1[2]==conn2[2])
9515         return true;
9516       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9517       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9518       return dist<eps;
9519     }
9520   else
9521     {//only one is quadratic
9522       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9523       if(!status0)
9524         return false;
9525       const double *a(0),*bb(0),*be(0);
9526       if(typ1.isQuadratic())
9527         {
9528           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9529         }
9530       else
9531         {
9532           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9533         }
9534       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9535       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9536       return dist<eps;
9537     }
9538 }
9539
9540 /*!
9541  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9542  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9543  *
9544  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9545  */
9546 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9547 {
9548   if(candidatesIn2DEnd==candidatesIn2DBg)
9549     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9550   const double *coo(mesh2DSplit->getCoords()->begin());
9551   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9552     return *candidatesIn2DBg;
9553   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9554   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9555   if(cellIdInMesh1DSplitRelative<0)
9556     cur1D->changeOrientationOfCells();
9557   const int *c1D(cur1D->getNodalConnectivity()->begin());
9558   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9559   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9560     {
9561       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9562       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9563       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9564       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9565       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9566       for(unsigned it2=0;it2<sz;it2++)
9567         {
9568           INTERP_KERNEL::NormalizedCellType typeOfSon;
9569           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9570           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9571           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9572             return *it;
9573         }
9574     }
9575   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9576 }
9577
9578 /// @endcond
9579
9580 /*!
9581  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9582  * 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
9583  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9584  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9585  *
9586  * \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
9587  *                      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)
9588  * \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
9589  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9590  * \param [in] eps - precision used to perform intersections and localization operations.
9591  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9592  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9593  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9594  *                               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.
9595  * \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
9596  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9597  *                               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.
9598  *
9599  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9600  */
9601 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9602 {
9603   if(!mesh2D || !mesh1D)
9604     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9605   mesh2D->checkFullyDefined();
9606   mesh1D->checkFullyDefined();
9607   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9608   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9609     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9610   // Step 1: compute all edge intersections (new nodes)
9611   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9612   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9613   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9614   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9615   //
9616   // Build desc connectivity
9617   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9618   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9619   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9620   std::map<int,int> mergedNodes;
9621   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9622   // use mergeNodes to fix intersectEdge1
9623   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9624     {
9625       std::size_t n((*it0).size()/2);
9626       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9627       std::map<int,int>::const_iterator it1;
9628       it1=mergedNodes.find(eltStart);
9629       if(it1!=mergedNodes.end())
9630         (*it0)[0]=(*it1).second;
9631       it1=mergedNodes.find(eltEnd);
9632       if(it1!=mergedNodes.end())
9633         (*it0)[2*n-1]=(*it1).second;
9634     }
9635   //
9636   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9637   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9638   // Step 2: re-order newly created nodes according to the ordering found in m2
9639   std::vector< std::vector<int> > intersectEdge2;
9640   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9641   subDiv2.clear();
9642   // Step 3: compute splitMesh1D
9643   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9644   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9645   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9646       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9647   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9648   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9649   // deal with cells in mesh2D that are not cut but only some of their edges are
9650   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9651   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9652   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9653   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
9654   if(!idsInDesc2DToBeRefined->empty())
9655     {
9656       DataArrayInt *out0(0),*outi0(0);
9657       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9658       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9659       out0s=out0;
9660       out0s=out0s->buildUnique();
9661       out0s->sort(true);
9662     }
9663   //
9664   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9665   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9666   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9667   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9668   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9669   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9670   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9671     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9672   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9673   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9674   if((DataArrayInt *)out0s)
9675     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9676   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9677   // OK all is ready to insert in ret2 mesh
9678   if(!untouchedCells->empty())
9679     {// the most easy part, cells in mesh2D not impacted at all
9680       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9681       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9682       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9683     }
9684   if((DataArrayInt *)out0s)
9685     {// here dealing with cells in out0s but not in cellsToBeModified
9686       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9687       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9688       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9689         {
9690           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9691           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9692         }
9693       int offset(ret2->getNumberOfTuples());
9694       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9695       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9696       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9697       int kk(0),*ret3ptr(partOfRet3->getPointer());
9698       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9699         {
9700           int faceId(std::abs(*it)-1);
9701           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9702             {
9703               int tmp(fewModifiedCells->locateValue(*it2));
9704               if(tmp!=-1)
9705                 {
9706                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9707                     ret3ptr[2*kk]=tmp+offset;
9708                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9709                     ret3ptr[2*kk+1]=tmp+offset;
9710                 }
9711               else
9712                 {//the current edge is shared by a 2D cell that will be split just after
9713                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9714                     ret3ptr[2*kk]=-(*it2+1);
9715                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9716                     ret3ptr[2*kk+1]=-(*it2+1);
9717                 }
9718             }
9719         }
9720       m1Desc->setCoords(ret1->getCoords());
9721       ret1NonCol->setCoords(ret1->getCoords());
9722       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9723       if(!outMesh2DSplit.empty())
9724         {
9725           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9726           for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9727             (*itt)->setCoords(da);
9728         }
9729     }
9730   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9731   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9732     {
9733       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9734       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9735       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9736       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9737       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9738       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));
9739       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9740       outMesh2DSplit.push_back(splitOfOneCell);
9741       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9742         ret2->pushBackSilent(*it);
9743     }
9744   //
9745   std::size_t nbOfMeshes(outMesh2DSplit.size());
9746   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9747   for(std::size_t i=0;i<nbOfMeshes;i++)
9748     tmp[i]=outMesh2DSplit[i];
9749   //
9750   ret1->getCoords()->setInfoOnComponents(compNames);
9751   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9752   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9753   ret3->rearrange(1);
9754   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9755   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9756     {
9757       int old2DCellId(-ret3->getIJ(*it,0)-1);
9758       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9759       ret3->setIJ(*it,0,FindRightCandidateAmong(ret2D,candidates->begin(),candidates->end(),ret1,*it%2==0?-((*it)/2+1):(*it)/2+1,eps));// div by 2 because 2 components natively in ret3
9760     }
9761   ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9762   ret3->rearrange(2);
9763   //
9764   splitMesh1D=ret1.retn();
9765   splitMesh2D=ret2D.retn();
9766   cellIdInMesh2D=ret2.retn();
9767   cellIdInMesh1D=ret3.retn();
9768 }
9769
9770 /**
9771  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9772  * (newly created) nodes corresponding to the edge intersections.
9773  * Output params:
9774  * @param[out] cr, crI connectivity of the resulting mesh
9775  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9776  * TODO: describe input parameters
9777  */
9778 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9779                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9780                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9781                                                          const std::vector<double>& addCoords,
9782                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9783 {
9784   static const int SPACEDIM=2;
9785   const double *coo1(m1->getCoords()->getConstPointer());
9786   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9787   int offset1(m1->getNumberOfNodes());
9788   const double *coo2(m2->getCoords()->getConstPointer());
9789   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9790   int offset2(offset1+m2->getNumberOfNodes());
9791   int offset3(offset2+((int)addCoords.size())/2);
9792   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9793   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9794   // Here a BBTree on 2D-cells, not on segments:
9795   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9796   int ncell1(m1->getNumberOfCells());
9797   crI.push_back(0);
9798   for(int i=0;i<ncell1;i++)
9799     {
9800       std::vector<int> candidates2;
9801       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9802       std::map<INTERP_KERNEL::Node *,int> mapp;
9803       std::map<int,INTERP_KERNEL::Node *> mappRev;
9804       INTERP_KERNEL::QuadraticPolygon pol1;
9805       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9806       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9807       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9808       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9809       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9810       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9811           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9812       //
9813       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
9814       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9815       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9816       for(it1.first();!it1.finished();it1.next())
9817         edges1.insert(it1.current()->getPtr());
9818       //
9819       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9820       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9821       int ii=0;
9822       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9823         {
9824           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9825           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9826           // Complete mapping with elements coming from the current cell it2 in mesh2:
9827           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9828           // pol2 is the new QP in the final merged result.
9829           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9830               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9831         }
9832       ii=0;
9833       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9834         {
9835           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9836           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9837           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9838           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9839         }
9840       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9841       // by m2 but that we still want to keep in the final result.
9842       if(!edges1.empty())
9843         {
9844           try
9845           {
9846               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9847           }
9848           catch(INTERP_KERNEL::Exception& e)
9849           {
9850               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();
9851               throw INTERP_KERNEL::Exception(oss.str().c_str());
9852           }
9853         }
9854       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9855         (*it).second->decrRef();
9856     }
9857 }
9858
9859 /**
9860  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9861  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9862  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9863  * The caller is to deal with the resulting DataArrayInt.
9864  *  \throw If the coordinate array is not set.
9865  *  \throw If the nodal connectivity of the cells is not defined.
9866  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9867  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9868  *
9869  * \sa DataArrayInt::sortEachPairToMakeALinkedList
9870  */
9871 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9872 {
9873   checkFullyDefined();
9874   if(getMeshDimension()!=1)
9875     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9876
9877   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9879   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9880   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9881   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9882   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9883   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9884   const int * dsi(_dsi->getConstPointer());
9885   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9886   m_points=0;
9887   if (dsii->getNumberOfTuples())
9888     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9889
9890   int nc(getNumberOfCells());
9891   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9892   result->alloc(nc,1);
9893
9894   // set of edges not used so far
9895   std::set<int> edgeSet;
9896   for (int i=0; i<nc; edgeSet.insert(i), i++);
9897
9898   int startSeg=0;
9899   int newIdx=0;
9900   // while we have points with only one neighbor segments
9901   do
9902     {
9903       std::list<int> linePiece;
9904       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9905       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9906         {
9907           // Fill the list forward (resp. backward) from the start segment:
9908           int activeSeg = startSeg;
9909           int prevPointId = -20;
9910           int ptId;
9911           while (!edgeSet.empty())
9912             {
9913               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9914                 {
9915                   if (direction==0)
9916                     linePiece.push_back(activeSeg);
9917                   else
9918                     linePiece.push_front(activeSeg);
9919                   edgeSet.erase(activeSeg);
9920                 }
9921
9922               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9923               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9924               if (dsi[ptId] == 1) // hitting the end of the line
9925                 break;
9926               prevPointId = ptId;
9927               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9928               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9929             }
9930         }
9931       // Done, save final piece into DA:
9932       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9933       newIdx += linePiece.size();
9934
9935       // identify next valid start segment (one which is not consumed)
9936       if(!edgeSet.empty())
9937         startSeg = *(edgeSet.begin());
9938     }
9939   while (!edgeSet.empty());
9940   return result.retn();
9941 }
9942
9943 /// @cond INTERNAL
9944
9945 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9946 {
9947   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9948   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9949   if(it==m.end())
9950     throw INTERP_KERNEL::Exception("Internal error in remapping !");
9951   int v((*it).second);
9952   if(v==forbVal0 || v==forbVal1)
9953     return ;
9954   if(std::find(isect.begin(),isect.end(),v)==isect.end())
9955     isect.push_back(v);
9956 }
9957
9958 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9959 {
9960   int sz(c.size());
9961   if(sz<=1)
9962     return false;
9963   bool presenceOfOn(false);
9964   for(int i=0;i<sz;i++)
9965     {
9966       INTERP_KERNEL::ElementaryEdge *e(c[i]);
9967       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9968         continue ;
9969       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9970       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9971     }
9972   return presenceOfOn;
9973 }
9974
9975 /// @endcond
9976
9977 /**
9978  * 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.
9979  * 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.
9980  * 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.
9981  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
9982  *
9983  * \return int - the number of new nodes created (in most of cases 0).
9984  * 
9985  * \throw If \a this is not coherent.
9986  * \throw If \a this has not spaceDim equal to 2.
9987  * \throw If \a this has not meshDim equal to 2.
9988  * \throw If some subcells needed to be split are orphan.
9989  * \sa MEDCouplingUMesh::conformize2D
9990  */
9991 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9992 {
9993   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9994     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9995   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9996   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9997     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9998   if(midOpt==0 && midOptI==0)
9999     {
10000       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10001       return 0;
10002     }
10003   else if(midOpt!=0 && midOptI!=0)
10004     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10005   else
10006     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10007 }
10008
10009 /*!
10010  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10011  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10012  * 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
10013  * 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).
10014  * 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.
10015  * 
10016  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10017  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10018  *
10019  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10020  * This method expects that all nodes in \a this are not closer than \a eps.
10021  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10022  * 
10023  * \param [in] eps the relative error to detect merged edges.
10024  * \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
10025  *                           that the user is expected to deal with.
10026  *
10027  * \throw If \a this is not coherent.
10028  * \throw If \a this has not spaceDim equal to 2.
10029  * \throw If \a this has not meshDim equal to 2.
10030  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10031  */
10032 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10033 {
10034   static const int SPACEDIM=2;
10035   checkCoherency();
10036   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10037     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10038   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10039   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10040   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10041   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10042   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10043   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10044   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10045   std::vector<double> addCoo;
10046   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10047   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10048   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10049   for(int i=0;i<nDescCell;i++)
10050     {
10051       std::vector<int> candidates;
10052       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10053       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10054         if(*it>i)
10055           {
10056             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10057             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10058                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10059             INTERP_KERNEL::MergePoints merge;
10060             INTERP_KERNEL::QuadraticPolygon c1,c2;
10061             e1->intersectWith(e2,merge,c1,c2);
10062             e1->decrRef(); e2->decrRef();
10063             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10064               overlapEdge[i].push_back(*it);
10065             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10066               overlapEdge[*it].push_back(i);
10067           }
10068     }
10069   // splitting done. sort intersect point in intersectEdge.
10070   std::vector< std::vector<int> > middle(nDescCell);
10071   int nbOf2DCellsToBeSplit(0);
10072   bool middleNeedsToBeUsed(false);
10073   std::vector<bool> cells2DToTreat(nDescCell,false);
10074   for(int i=0;i<nDescCell;i++)
10075     {
10076       std::vector<int>& isect(intersectEdge[i]);
10077       int sz((int)isect.size());
10078       if(sz>1)
10079         {
10080           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10081           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10082           e->sortSubNodesAbs(coords,isect);
10083           e->decrRef();
10084         }
10085       if(sz!=0)
10086         {
10087           int idx0(rdi[i]),idx1(rdi[i+1]);
10088           if(idx1-idx0!=1)
10089             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10090           if(!cells2DToTreat[rd[idx0]])
10091             {
10092               cells2DToTreat[rd[idx0]]=true;
10093               nbOf2DCellsToBeSplit++;
10094             }
10095           // try to reuse at most eventual 'middle' of SEG3
10096           std::vector<int>& mid(middle[i]);
10097           mid.resize(sz+1,-1);
10098           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10099             {
10100               middleNeedsToBeUsed=true;
10101               const std::vector<int>& candidates(overlapEdge[i]);
10102               std::vector<int> trueCandidates;
10103               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10104                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10105                   trueCandidates.push_back(*itc);
10106               int stNode(c[ci[i]+1]),endNode(isect[0]);
10107               for(int j=0;j<sz+1;j++)
10108                 {
10109                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10110                     {
10111                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10112                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10113                         { mid[j]=*itc; break; }
10114                     }
10115                   stNode=endNode;
10116                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10117                 }
10118             }
10119         }
10120     }
10121   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10122   if(nbOf2DCellsToBeSplit==0)
10123     return ret.retn();
10124   //
10125   int *retPtr(ret->getPointer());
10126   for(int i=0;i<nCell;i++)
10127     if(cells2DToTreat[i])
10128       *retPtr++=i;
10129   //
10130   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10131   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10132   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10133   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10134   if(middleNeedsToBeUsed)
10135     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10136   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10137   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10138   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.
10139   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10140   {
10141     bool areNodesMerged; int newNbOfNodes;
10142     if(nbOfNodesCreated!=0)
10143       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10144   }
10145   return ret.retn();
10146 }
10147
10148 /*!
10149  * 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.
10150  * 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).
10151  * 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
10152  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10153  * 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
10154  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10155  *
10156  * 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
10157  * using new instance, idem for coordinates.
10158  *
10159  * 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.
10160  * 
10161  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10162  *
10163  * \throw If \a this is not coherent.
10164  * \throw If \a this has not spaceDim equal to 2.
10165  * \throw If \a this has not meshDim equal to 2.
10166  * 
10167  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10168  */
10169 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10170 {
10171   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10172   checkCoherency();
10173   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10174     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10175   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10176   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10177   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10178   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10179   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10180   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10181   const double *coords(_coords->begin());
10182   int *newciptr(newci->getPointer());
10183   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10184     {
10185       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10186         ret->pushBackSilent(i);
10187       newciptr[1]=newc->getNumberOfTuples();
10188     }
10189   //
10190   if(ret->empty())
10191     return ret.retn();
10192   if(!appendedCoords->empty())
10193     {
10194       appendedCoords->rearrange(2);
10195       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10196       //non const part
10197       setCoords(newCoords);
10198     }
10199   //non const part
10200   setConnectivity(newc,newci,true);
10201   return ret.retn();
10202 }
10203
10204 /*!
10205  * \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.
10206  *                               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.
10207  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10208  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10209  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10210  * \param [out] addCoo - nodes to be append at the end
10211  * \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.
10212  */
10213 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10214                                          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)
10215 {
10216   static const int SPACEDIM=2;
10217   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10218   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10219   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10220   // Build BB tree of all edges in the tool mesh (second mesh)
10221   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10222   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10223   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10224   intersectEdge1.resize(nDescCell1);
10225   colinear2.resize(nDescCell2);
10226   subDiv2.resize(nDescCell2);
10227   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10228
10229   std::vector<int> candidates1(1);
10230   int offset1(m1Desc->getNumberOfNodes());
10231   int offset2(offset1+m2Desc->getNumberOfNodes());
10232   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10233     {
10234       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10235       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10236       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10237         {
10238           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10239           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10240           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10241           candidates1[0]=i;
10242           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10243           // 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
10244           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10245           std::set<INTERP_KERNEL::Node *> nodes;
10246           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10247           std::size_t szz(nodes.size());
10248           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10249           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10250           for(std::size_t iii=0;iii<szz;iii++,itt++)
10251             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10252           // end of protection
10253           // Performs egde cutting:
10254           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10255           delete pol2;
10256           delete pol1;
10257         }
10258       else
10259         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10260         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10261     }
10262 }
10263
10264 /*!
10265  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10266  * It builds the descending connectivity of the two meshes, and then using a binary tree
10267  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10268  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10269  */
10270 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10271                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10272                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10273                                                    std::vector<double>& addCoo,
10274                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10275 {
10276   // Build desc connectivity
10277   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10278   desc2=DataArrayInt::New();
10279   descIndx2=DataArrayInt::New();
10280   revDesc2=DataArrayInt::New();
10281   revDescIndx2=DataArrayInt::New();
10282   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10283   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10284   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10285   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10286   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10287   std::map<int,int> notUsedMap;
10288   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10289   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10290   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10291 }
10292
10293 /*!
10294  * This method performs the 2nd step of Partition of 2D mesh.
10295  * This method has 4 inputs :
10296  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10297  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10298  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10299  * 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'
10300  * Nodes end up lying consecutively on a cutted edge.
10301  * \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.
10302  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10303  * \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.
10304  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10305  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10306  */
10307 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10308                                            const std::vector<double>& addCoo,
10309                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10310 {
10311   int offset1=m1->getNumberOfNodes();
10312   int ncell=m2->getNumberOfCells();
10313   const int *c=m2->getNodalConnectivity()->getConstPointer();
10314   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10315   const double *coo=m2->getCoords()->getConstPointer();
10316   const double *cooBis=m1->getCoords()->getConstPointer();
10317   int offset2=offset1+m2->getNumberOfNodes();
10318   intersectEdge.resize(ncell);
10319   for(int i=0;i<ncell;i++,cI++)
10320     {
10321       const std::vector<int>& divs=subDiv[i];
10322       int nnode=cI[1]-cI[0]-1;
10323       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10324       std::map<INTERP_KERNEL::Node *, int> mapp22;
10325       for(int j=0;j<nnode;j++)
10326         {
10327           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10328           int nnid=c[(*cI)+j+1];
10329           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10330           mapp22[nn]=nnid+offset1;
10331         }
10332       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10333       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10334         ((*it).second.first)->decrRef();
10335       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10336       std::map<INTERP_KERNEL::Node *,int> mapp3;
10337       for(std::size_t j=0;j<divs.size();j++)
10338         {
10339           int id=divs[j];
10340           INTERP_KERNEL::Node *tmp=0;
10341           if(id<offset1)
10342             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10343           else if(id<offset2)
10344             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10345           else
10346             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10347           addNodes[j]=tmp;
10348           mapp3[tmp]=id;
10349         }
10350       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10351       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10352         (*it)->decrRef();
10353       e->decrRef();
10354     }
10355 }
10356
10357 /*!
10358  * 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).
10359  * 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
10360  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10361  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10362  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10363  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10364  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10365  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10366  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10367  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10368  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10369  * \param [out] cut3DSuf input/output param.
10370  */
10371 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10372                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10373                                                    const int *desc, const int *descIndx, 
10374                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10375 {
10376   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10377   int nbOf3DSurfCell=(int)cut3DSurf.size();
10378   for(int i=0;i<nbOf3DSurfCell;i++)
10379     {
10380       std::vector<int> res;
10381       int offset=descIndx[i];
10382       int nbOfSeg=descIndx[i+1]-offset;
10383       for(int j=0;j<nbOfSeg;j++)
10384         {
10385           int edgeId=desc[offset+j];
10386           int status=cut3DCurve[edgeId];
10387           if(status!=-2)
10388             {
10389               if(status>-1)
10390                 res.push_back(status);
10391               else
10392                 {
10393                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10394                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10395                 }
10396             }
10397         }
10398       switch(res.size())
10399       {
10400         case 2:
10401           {
10402             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10403             break;
10404           }
10405         case 1:
10406         case 0:
10407           {
10408             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10409             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10410             if(res.size()==2)
10411               {
10412                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10413               }
10414             else
10415               {
10416                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10417               }
10418             break;
10419           }
10420         default:
10421           {// case when plane is on a multi colinear edge of a polyhedron
10422             if((int)res.size()==2*nbOfSeg)
10423               {
10424                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10425               }
10426             else
10427               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10428           }
10429       }
10430     }
10431 }
10432
10433 /*!
10434  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10435  * 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).
10436  * 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
10437  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10438  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10439  * \param desc is the descending connectivity 3D->3DSurf
10440  * \param descIndx is the descending connectivity index 3D->3DSurf
10441  */
10442 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10443                                                   const int *desc, const int *descIndx,
10444                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10445 {
10446   checkFullyDefined();
10447   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10448     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10449   const int *nodal3D=_nodal_connec->getConstPointer();
10450   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10451   int nbOfCells=getNumberOfCells();
10452   for(int i=0;i<nbOfCells;i++)
10453     {
10454       std::map<int, std::set<int> > m;
10455       int offset=descIndx[i];
10456       int nbOfFaces=descIndx[i+1]-offset;
10457       int start=-1;
10458       int end=-1;
10459       for(int j=0;j<nbOfFaces;j++)
10460         {
10461           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10462           if(p.first!=-1 && p.second!=-1)
10463             {
10464               if(p.first!=-2)
10465                 {
10466                   start=p.first; end=p.second;
10467                   m[p.first].insert(p.second);
10468                   m[p.second].insert(p.first);
10469                 }
10470               else
10471                 {
10472                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10473                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10474                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10475                   INTERP_KERNEL::NormalizedCellType cmsId;
10476                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10477                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10478                   for(unsigned k=0;k<nbOfNodesSon;k++)
10479                     {
10480                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10481                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10482                     }
10483                 }
10484             }
10485         }
10486       if(m.empty())
10487         continue;
10488       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10489       int prev=end;
10490       while(end!=start)
10491         {
10492           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10493           const std::set<int>& s=(*it).second;
10494           std::set<int> s2; s2.insert(prev);
10495           std::set<int> s3;
10496           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10497           if(s3.size()==1)
10498             {
10499               int val=*s3.begin();
10500               conn.push_back(start);
10501               prev=start;
10502               start=val;
10503             }
10504           else
10505             start=end;
10506         }
10507       conn.push_back(end);
10508       if(conn.size()>3)
10509         {
10510           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10511           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10512           cellIds->pushBackSilent(i);
10513         }
10514     }
10515 }
10516
10517 /*!
10518  * 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
10519  * 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
10520  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10521  * 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
10522  * 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.
10523  * 
10524  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10525  */
10526 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10527 {
10528   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10529   if(sz>=4)
10530     {
10531       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10532       if(cm.getDimension()==2)
10533         {
10534           const int *node=nodalConnBg+1;
10535           int startNode=*node++;
10536           double refX=coords[2*startNode];
10537           for(;node!=nodalConnEnd;node++)
10538             {
10539               if(coords[2*(*node)]<refX)
10540                 {
10541                   startNode=*node;
10542                   refX=coords[2*startNode];
10543                 }
10544             }
10545           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10546           refX=1e300;
10547           double tmp1;
10548           double tmp2[2];
10549           double angle0=-M_PI/2;
10550           //
10551           int nextNode=-1;
10552           int prevNode=-1;
10553           double resRef;
10554           double angleNext=0.;
10555           while(nextNode!=startNode)
10556             {
10557               nextNode=-1;
10558               resRef=1e300;
10559               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10560                 {
10561                   if(*node!=tmpOut.back() && *node!=prevNode)
10562                     {
10563                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10564                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10565                       double res;
10566                       if(angleM<=angle0)
10567                         res=angle0-angleM;
10568                       else
10569                         res=angle0-angleM+2.*M_PI;
10570                       if(res<resRef)
10571                         {
10572                           nextNode=*node;
10573                           resRef=res;
10574                           angleNext=angleM;
10575                         }
10576                     }
10577                 }
10578               if(nextNode!=startNode)
10579                 {
10580                   angle0=angleNext-M_PI;
10581                   if(angle0<-M_PI)
10582                     angle0+=2*M_PI;
10583                   prevNode=tmpOut.back();
10584                   tmpOut.push_back(nextNode);
10585                 }
10586             }
10587           std::vector<int> tmp3(2*(sz-1));
10588           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10589           std::copy(nodalConnBg+1,nodalConnEnd,it);
10590           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10591             {
10592               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10593               return false;
10594             }
10595           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10596             {
10597               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10598               return false;
10599             }
10600           else
10601             {
10602               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10603               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10604               return true;
10605             }
10606         }
10607       else
10608         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10609     }
10610   else
10611     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10612 }
10613
10614 /*!
10615  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10616  * 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.
10617  * 
10618  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10619  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10620  * \param [in,out] arr array in which the remove operation will be done.
10621  * \param [in,out] arrIndx array in the remove operation will modify
10622  * \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])
10623  * \return true if \b arr and \b arrIndx have been modified, false if not.
10624  */
10625 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10626 {
10627   if(!arrIndx || !arr)
10628     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10629   if(offsetForRemoval<0)
10630     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10631   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10632   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10633   int *arrIPtr=arrIndx->getPointer();
10634   *arrIPtr++=0;
10635   int previousArrI=0;
10636   const int *arrPtr=arr->getConstPointer();
10637   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10638   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10639     {
10640       if(*arrIPtr-previousArrI>offsetForRemoval)
10641         {
10642           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10643             {
10644               if(s.find(*work)==s.end())
10645                 arrOut.push_back(*work);
10646             }
10647         }
10648       previousArrI=*arrIPtr;
10649       *arrIPtr=(int)arrOut.size();
10650     }
10651   if(arr->getNumberOfTuples()==(int)arrOut.size())
10652     return false;
10653   arr->alloc((int)arrOut.size(),1);
10654   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10655   return true;
10656 }
10657
10658 /*!
10659  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10660  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10661  * The selection of extraction is done standardly in new2old format.
10662  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10663  *
10664  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10665  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10666  * \param [in] arrIn arr origin array from which the extraction will be done.
10667  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10668  * \param [out] arrOut the resulting array
10669  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10670  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10671  */
10672 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10673                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10674 {
10675   if(!arrIn || !arrIndxIn)
10676     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10677   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10678   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10679     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10680   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10681   const int *arrInPtr=arrIn->getConstPointer();
10682   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10683   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10684   if(nbOfGrps<0)
10685     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10686   int maxSizeOfArr=arrIn->getNumberOfTuples();
10687   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10688   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10689   arrIo->alloc((int)(sz+1),1);
10690   const int *idsIt=idsOfSelectBg;
10691   int *work=arrIo->getPointer();
10692   *work++=0;
10693   int lgth=0;
10694   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10695     {
10696       if(*idsIt>=0 && *idsIt<nbOfGrps)
10697         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10698       else
10699         {
10700           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10701           throw INTERP_KERNEL::Exception(oss.str().c_str());
10702         }
10703       if(lgth>=work[-1])
10704         *work=lgth;
10705       else
10706         {
10707           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10708           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10709           throw INTERP_KERNEL::Exception(oss.str().c_str());
10710         }
10711     }
10712   arro->alloc(lgth,1);
10713   work=arro->getPointer();
10714   idsIt=idsOfSelectBg;
10715   for(std::size_t i=0;i<sz;i++,idsIt++)
10716     {
10717       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10718         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10719       else
10720         {
10721           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10722           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10723           throw INTERP_KERNEL::Exception(oss.str().c_str());
10724         }
10725     }
10726   arrOut=arro.retn();
10727   arrIndexOut=arrIo.retn();
10728 }
10729
10730 /*!
10731  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10732  * 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 ).
10733  * The selection of extraction is done standardly in new2old format.
10734  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10735  *
10736  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10737  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10738  * \param [in] arrIn arr origin array from which the extraction will be done.
10739  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10740  * \param [out] arrOut the resulting array
10741  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10742  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10743  */
10744 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10745                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10746 {
10747   if(!arrIn || !arrIndxIn)
10748     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10749   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10750   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10751     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10752   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10753   const int *arrInPtr=arrIn->getConstPointer();
10754   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10755   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10756   if(nbOfGrps<0)
10757     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10758   int maxSizeOfArr=arrIn->getNumberOfTuples();
10759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10761   arrIo->alloc((int)(sz+1),1);
10762   int idsIt=idsOfSelectStart;
10763   int *work=arrIo->getPointer();
10764   *work++=0;
10765   int lgth=0;
10766   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10767     {
10768       if(idsIt>=0 && idsIt<nbOfGrps)
10769         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10770       else
10771         {
10772           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10773           throw INTERP_KERNEL::Exception(oss.str().c_str());
10774         }
10775       if(lgth>=work[-1])
10776         *work=lgth;
10777       else
10778         {
10779           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10780           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10781           throw INTERP_KERNEL::Exception(oss.str().c_str());
10782         }
10783     }
10784   arro->alloc(lgth,1);
10785   work=arro->getPointer();
10786   idsIt=idsOfSelectStart;
10787   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10788     {
10789       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10790         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10791       else
10792         {
10793           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10794           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10795           throw INTERP_KERNEL::Exception(oss.str().c_str());
10796         }
10797     }
10798   arrOut=arro.retn();
10799   arrIndexOut=arrIo.retn();
10800 }
10801
10802 /*!
10803  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10804  * 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
10805  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10806  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10807  *
10808  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10809  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10810  * \param [in] arrIn arr origin array from which the extraction will be done.
10811  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10812  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10813  * \param [in] srcArrIndex index array of \b srcArr
10814  * \param [out] arrOut the resulting array
10815  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10816  * 
10817  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10818  */
10819 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10820                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10821                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10822 {
10823   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10824     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10825   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10826   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10827   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10828   std::vector<bool> v(nbOfTuples,true);
10829   int offset=0;
10830   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10831   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10832   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10833     {
10834       if(*it>=0 && *it<nbOfTuples)
10835         {
10836           v[*it]=false;
10837           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10838         }
10839       else
10840         {
10841           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10842           throw INTERP_KERNEL::Exception(oss.str().c_str());
10843         }
10844     }
10845   srcArrIndexPtr=srcArrIndex->getConstPointer();
10846   arrIo->alloc(nbOfTuples+1,1);
10847   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10848   const int *arrInPtr=arrIn->getConstPointer();
10849   const int *srcArrPtr=srcArr->getConstPointer();
10850   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10851   int *arroPtr=arro->getPointer();
10852   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10853     {
10854       if(v[ii])
10855         {
10856           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10857           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10858         }
10859       else
10860         {
10861           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10862           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10863           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10864         }
10865     }
10866   arrOut=arro.retn();
10867   arrIndexOut=arrIo.retn();
10868 }
10869
10870 /*!
10871  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10872  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10873  *
10874  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10875  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10876  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10877  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10878  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10879  * \param [in] srcArrIndex index array of \b srcArr
10880  * 
10881  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10882  */
10883 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10884                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10885 {
10886   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10887     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10888   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10889   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10890   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10891   int *arrInOutPtr=arrInOut->getPointer();
10892   const int *srcArrPtr=srcArr->getConstPointer();
10893   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10894     {
10895       if(*it>=0 && *it<nbOfTuples)
10896         {
10897           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10898             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10899           else
10900             {
10901               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] !";
10902               throw INTERP_KERNEL::Exception(oss.str().c_str());
10903             }
10904         }
10905       else
10906         {
10907           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10908           throw INTERP_KERNEL::Exception(oss.str().c_str());
10909         }
10910     }
10911 }
10912
10913 /*!
10914  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10915  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10916  * 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]].
10917  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10918  * A negative value in \b arrIn means that it is ignored.
10919  * 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.
10920  * 
10921  * \param [in] arrIn arr origin array from which the extraction will be done.
10922  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10923  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10924  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10925  */
10926 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10927 {
10928   int seed=0,nbOfDepthPeelingPerformed=0;
10929   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10930 }
10931
10932 /*!
10933  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10934  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10935  * 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]].
10936  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10937  * A negative value in \b arrIn means that it is ignored.
10938  * 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.
10939  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10940  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10941  * \param [in] arrIn arr origin array from which the extraction will be done.
10942  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10943  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10944  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10945  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10946  * \sa MEDCouplingUMesh::partitionBySpreadZone
10947  */
10948 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10949 {
10950   nbOfDepthPeelingPerformed=0;
10951   if(!arrIndxIn)
10952     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10953   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10954   if(nbOfTuples<=0)
10955     {
10956       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10957       return ret;
10958     }
10959   //
10960   std::vector<bool> fetched(nbOfTuples,false);
10961   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10962 }
10963
10964 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10965 {
10966   nbOfDepthPeelingPerformed=0;
10967   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10968     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10969   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10970   std::vector<bool> fetched2(nbOfTuples,false);
10971   int i=0;
10972   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10973     {
10974       if(*seedElt>=0 && *seedElt<nbOfTuples)
10975         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10976       else
10977         { 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()); }
10978     }
10979   const int *arrInPtr=arrIn->getConstPointer();
10980   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10981   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
10982   std::vector<int> idsToFetch1(seedBg,seedEnd);
10983   std::vector<int> idsToFetch2;
10984   std::vector<int> *idsToFetch=&idsToFetch1;
10985   std::vector<int> *idsToFetchOther=&idsToFetch2;
10986   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
10987     {
10988       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
10989         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
10990           if(!fetched[*it2])
10991             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10992       std::swap(idsToFetch,idsToFetchOther);
10993       idsToFetchOther->clear();
10994       nbOfDepthPeelingPerformed++;
10995     }
10996   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10997   i=0;
10998   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10999   int *retPtr=ret->getPointer();
11000   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11001     if(*it)
11002       *retPtr++=i;
11003   return ret.retn();
11004 }
11005
11006 /*!
11007  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11008  * 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
11009  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11010  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11011  *
11012  * \param [in] start begin of set of ids of the input extraction (included)
11013  * \param [in] end end of set of ids of the input extraction (excluded)
11014  * \param [in] step step of the set of ids in range mode.
11015  * \param [in] arrIn arr origin array from which the extraction will be done.
11016  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11017  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11018  * \param [in] srcArrIndex index array of \b srcArr
11019  * \param [out] arrOut the resulting array
11020  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11021  * 
11022  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11023  */
11024 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11025                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11026                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11027 {
11028   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11029     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11030   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11031   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11032   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11033   int offset=0;
11034   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11035   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11036   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11037   int it=start;
11038   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11039     {
11040       if(it>=0 && it<nbOfTuples)
11041         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11042       else
11043         {
11044           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11045           throw INTERP_KERNEL::Exception(oss.str().c_str());
11046         }
11047     }
11048   srcArrIndexPtr=srcArrIndex->getConstPointer();
11049   arrIo->alloc(nbOfTuples+1,1);
11050   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11051   const int *arrInPtr=arrIn->getConstPointer();
11052   const int *srcArrPtr=srcArr->getConstPointer();
11053   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11054   int *arroPtr=arro->getPointer();
11055   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11056     {
11057       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11058       if(pos<0)
11059         {
11060           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11061           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11062         }
11063       else
11064         {
11065           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11066           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11067         }
11068     }
11069   arrOut=arro.retn();
11070   arrIndexOut=arrIo.retn();
11071 }
11072
11073 /*!
11074  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11075  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11076  *
11077  * \param [in] start begin of set of ids of the input extraction (included)
11078  * \param [in] end end of set of ids of the input extraction (excluded)
11079  * \param [in] step step of the set of ids in range mode.
11080  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11081  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11082  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11083  * \param [in] srcArrIndex index array of \b srcArr
11084  * 
11085  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11086  */
11087 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11088                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11089 {
11090   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11091     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11092   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11093   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11094   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11095   int *arrInOutPtr=arrInOut->getPointer();
11096   const int *srcArrPtr=srcArr->getConstPointer();
11097   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11098   int it=start;
11099   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11100     {
11101       if(it>=0 && it<nbOfTuples)
11102         {
11103           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11104             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11105           else
11106             {
11107               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11108               throw INTERP_KERNEL::Exception(oss.str().c_str());
11109             }
11110         }
11111       else
11112         {
11113           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11114           throw INTERP_KERNEL::Exception(oss.str().c_str());
11115         }
11116     }
11117 }
11118
11119 /*!
11120  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11121  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11122  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11123  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11124  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11125  * 
11126  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11127  */
11128 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11129 {
11130   checkFullyDefined();
11131   int mdim=getMeshDimension();
11132   int spaceDim=getSpaceDimension();
11133   if(mdim!=spaceDim)
11134     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11135   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11136   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11137   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11138   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11139   ret->setCoords(getCoords());
11140   ret->allocateCells((int)partition.size());
11141   //
11142   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11143     {
11144       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11145       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11146       switch(mdim)
11147       {
11148         case 2:
11149           cell=tmp->buildUnionOf2DMesh();
11150           break;
11151         case 3:
11152           cell=tmp->buildUnionOf3DMesh();
11153           break;
11154         default:
11155           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11156       }
11157
11158       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11159     }
11160   //
11161   ret->finishInsertingCells();
11162   return ret.retn();
11163 }
11164
11165 /*!
11166  * This method partitions \b this into contiguous zone.
11167  * This method only needs a well defined connectivity. Coordinates are not considered here.
11168  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11169  */
11170 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11171 {
11172   int nbOfCellsCur=getNumberOfCells();
11173   std::vector<DataArrayInt *> ret;
11174   if(nbOfCellsCur<=0)
11175     return ret;
11176   DataArrayInt *neigh=0,*neighI=0;
11177   computeNeighborsOfCells(neigh,neighI);
11178   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11179   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11180   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11181   int seed=0;
11182   while(seed<nbOfCellsCur)
11183     {
11184       int nbOfPeelPerformed=0;
11185       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11186       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11187     }
11188   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11189     ret.push_back((*it).retn());
11190   return ret;
11191 }
11192
11193 /*!
11194  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11195  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11196  *
11197  * \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.
11198  * \return a newly allocated DataArrayInt to be managed by the caller.
11199  * \throw In case of \a code has not the right format (typically of size 3*n)
11200  */
11201 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11202 {
11203   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11204   std::size_t nb=code.size()/3;
11205   if(code.size()%3!=0)
11206     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11207   ret->alloc((int)nb,2);
11208   int *retPtr=ret->getPointer();
11209   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11210     {
11211       retPtr[0]=code[3*i+2];
11212       retPtr[1]=code[3*i+2]+code[3*i+1];
11213     }
11214   return ret.retn();
11215 }
11216
11217 /*!
11218  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11219  * All cells in \a this are expected to be linear 3D cells.
11220  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11221  * It leads to an increase to number of cells.
11222  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11223  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11224  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11225  *
11226  * \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.
11227  *                      For all other cells, the splitting policy will be ignored.
11228  * \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. 
11229  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11230  *          an id of old cell producing it. The caller is to delete this array using
11231  *         decrRef() as it is no more needed.
11232  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11233  *
11234  * \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
11235  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11236  * 
11237  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11238  * \throw If \a this is not fully constituted with linear 3D cells.
11239  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11240  */
11241 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11242 {
11243   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11244   checkConnectivityFullyDefined();
11245   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11246     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11247   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11248   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11249   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11250   int *retPt(ret->getPointer());
11251   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11252   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11253   const int *oldc(_nodal_connec->begin());
11254   const int *oldci(_nodal_connec_index->begin());
11255   const double *coords(_coords->begin());
11256   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11257     {
11258       std::vector<int> a; std::vector<double> b;
11259       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11260       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11261       const int *aa(&a[0]);
11262       if(!b.empty())
11263         {
11264           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11265             if(*it<0)
11266               *it=(-(*(it))-1+nbNodes);
11267           addPts->insertAtTheEnd(b.begin(),b.end());
11268           nbNodes+=(int)b.size()/3;
11269         }
11270       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11271         newConn->insertAtTheEnd(aa,aa+4);
11272     }
11273   if(!addPts->empty())
11274     {
11275       addPts->rearrange(3);
11276       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11277       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11278       ret0->setCoords(addPts);
11279     }
11280   else
11281     {
11282       nbOfAdditionalPoints=0;
11283       ret0->setCoords(getCoords());
11284     }
11285   ret0->setNodalConnectivity(newConn);
11286   //
11287   ret->computeOffsets2();
11288   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11289   return ret0.retn();
11290 }
11291
11292 /*!
11293  * 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). 
11294  *
11295  * \sa MEDCouplingUMesh::split2DCells
11296  */
11297 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11298 {
11299   checkConnectivityFullyDefined();
11300   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11301   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11302   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11303   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11304   int prevPosOfCi(ciPtr[0]);
11305   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11306     {
11307       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11308       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11309       for(int j=0;j<sz;j++)
11310         {
11311           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11312           for(int k=0;k<sz2;k++)
11313             *cPtr++=subPtr[offset2+k];
11314           if(j!=sz-1)
11315             *cPtr++=oldConn[prevPosOfCi+j+2];
11316           deltaSz+=sz2;
11317         }
11318       prevPosOfCi=ciPtr[1];
11319       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11320     }
11321   if(c->end()!=cPtr)
11322     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11323   _nodal_connec->decrRef();
11324   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11325 }
11326
11327 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11328 {
11329   if(id!=-1)
11330     return id;
11331   else
11332     {
11333       int ret(nodesCnter++);
11334       double newPt[2];
11335       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11336       addCoo.insertAtTheEnd(newPt,newPt+2);
11337       return ret;
11338     }
11339 }
11340
11341 /// @cond INTERNAL
11342
11343 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)
11344 {
11345   int tmp[3];
11346   int trueStart(start>=0?start:nbOfEdges+start);
11347   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11348   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11349   if(linOrArc)
11350     {
11351       if(stp-start>1)
11352         {
11353           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11354           InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11355           middles.push_back(tmp3+offset);
11356         }
11357       else
11358         middles.push_back(connBg[trueStart+nbOfEdges]);
11359     }
11360 }
11361
11362 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)
11363 {
11364   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11365   newConnOfCell->pushBackSilent(tmpEnd);
11366   if(linOrArc)
11367     {
11368       if(stp-start>1)
11369         {
11370           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11371           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11372           middles.push_back(tmp3+offset);
11373         }
11374       else
11375         middles.push_back(connBg[start+nbOfEdges]);
11376     }
11377 }
11378
11379 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)
11380 {
11381   if(linOrArc)
11382     {
11383       if(stp-start>1)
11384         {
11385           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11386           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11387           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11388           middles.push_back(tmp3+offset);
11389         }
11390       else
11391         middles.push_back(connBg[start+nbOfEdges]);
11392     }
11393 }
11394
11395 /// @cond INTERNAL
11396
11397 /*!
11398  * 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 ) .
11399  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11400  */
11401 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11402 {
11403   std::size_t sz(std::distance(connBg,connEnd));
11404   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11405     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11406   sz--;
11407   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11408   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11409   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
11410   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11411   INTERP_KERNEL::NormalizedCellType typeOfSon;
11412   std::vector<int> middles;
11413   bool ret(false);
11414   for(;nbOfHit<nbs;nbOfTurn++)
11415     {
11416       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11417       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11418       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11419       posEndElt++;
11420       nbOfHit++;
11421       unsigned endI(nbs-nbOfHit);
11422       for(unsigned i=0;i<endI;i++)
11423         {
11424           cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
11425           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11426           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11427           bool isColinear(eint->areColinears());
11428           if(isColinear)
11429             {
11430               nbOfHit++;
11431               posEndElt++;
11432               ret=true;
11433             }
11434           delete eint;
11435           eCand->decrRef();
11436           if(!isColinear)
11437             {
11438               if(nbOfTurn==0)
11439                 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
11440                   unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
11441                   for(unsigned ii=0;ii<endII;ii++)
11442                     {
11443                       cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
11444                       eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
11445                       eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
11446                       isColinear=eint->areColinears();
11447                       if(isColinear)
11448                         {
11449                           nbOfHit++;
11450                           posBaseElt--;
11451                           ret=true;
11452                         }
11453                       delete eint;
11454                       eCand->decrRef();
11455                       if(!isColinear)
11456                         break;
11457                     }
11458                 }
11459               break;
11460             }
11461         }
11462       //push [posBaseElt,posEndElt) in newConnOfCell using e
11463       if(nbOfTurn==0)
11464         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11465       else if(nbOfHit!=nbs)
11466         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11467       else
11468         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11469       posBaseElt=posEndElt;
11470       e->decrRef();
11471     }
11472   if(!middles.empty())
11473     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11474   return ret;
11475 }
11476
11477 /*!
11478  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11479  *
11480  * \return  int - the number of new nodes created.
11481  * \sa MEDCouplingUMesh::split2DCells
11482  */
11483 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11484 {
11485   checkCoherency();
11486   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11487   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11488   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11489   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11490   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11491   const double *oldCoordsPtr(getCoords()->begin());
11492   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11493   int prevPosOfCi(ciPtr[0]);
11494   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11495     {
11496       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11497       for(int j=0;j<sz;j++)
11498         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11499       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11500       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11501         {
11502           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11503           if(sz2==0)
11504             {
11505               if(j<sz-1)
11506                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11507               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11508               continue;
11509             }
11510           std::vector<INTERP_KERNEL::Node *> ns(3);
11511           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11512           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11513           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11514           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11515           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11516             {
11517               cPtr[1]=subPtr[offset2+k];
11518               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11519             }
11520           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11521           if(j!=sz-1)
11522             { cPtr[1]=tmpEnd; }
11523           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11524         }
11525       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11526       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11527     }
11528   if(c->end()!=cPtr)
11529     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11530   _nodal_connec->decrRef();
11531   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11532   addCoo->rearrange(2);
11533   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11534   setCoords(coo);
11535   return addCoo->getNumberOfTuples();
11536 }
11537
11538 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11539     _own_cell(true),_cell_id(-1),_nb_cell(0)
11540 {
11541   if(mesh)
11542     {
11543       mesh->incrRef();
11544       _nb_cell=mesh->getNumberOfCells();
11545     }
11546 }
11547
11548 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11549 {
11550   if(_mesh)
11551     _mesh->decrRef();
11552   if(_own_cell)
11553     delete _cell;
11554 }
11555
11556 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11557     _own_cell(false),_cell_id(bg-1),
11558     _nb_cell(end)
11559 {
11560   if(mesh)
11561     mesh->incrRef();
11562 }
11563
11564 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11565 {
11566   _cell_id++;
11567   if(_cell_id<_nb_cell)
11568     {
11569       _cell->next();
11570       return _cell;
11571     }
11572   else
11573     return 0;
11574 }
11575
11576 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11577 {
11578   if(_mesh)
11579     _mesh->incrRef();
11580 }
11581
11582 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11583 {
11584   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11585 }
11586
11587 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11588 {
11589   if(_mesh)
11590     _mesh->decrRef();
11591 }
11592
11593 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11594     _itc(itc),
11595     _bg(bg),_end(end)
11596 {
11597   if(_mesh)
11598     _mesh->incrRef();
11599 }
11600
11601 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11602 {
11603   if(_mesh)
11604     _mesh->decrRef();
11605 }
11606
11607 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11608 {
11609   return _type;
11610 }
11611
11612 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11613 {
11614   return _end-_bg;
11615 }
11616
11617 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11618 {
11619   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11620 }
11621
11622 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11623 {
11624   if(mesh)
11625     {
11626       mesh->incrRef();
11627       _nb_cell=mesh->getNumberOfCells();
11628     }
11629 }
11630
11631 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11632 {
11633   if(_mesh)
11634     _mesh->decrRef();
11635   delete _cell;
11636 }
11637
11638 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11639 {
11640   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11641   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11642   if(_cell_id<_nb_cell)
11643     {
11644       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11645       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11646       int startId=_cell_id;
11647       _cell_id+=nbOfElems;
11648       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11649     }
11650   else
11651     return 0;
11652 }
11653
11654 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11655 {
11656   if(mesh)
11657     {
11658       _conn=mesh->getNodalConnectivity()->getPointer();
11659       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11660     }
11661 }
11662
11663 void MEDCouplingUMeshCell::next()
11664 {
11665   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11666     {
11667       _conn+=_conn_lgth;
11668       _conn_indx++;
11669     }
11670   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11671 }
11672
11673 std::string MEDCouplingUMeshCell::repr() const
11674 {
11675   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11676     {
11677       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11678       oss << " : ";
11679       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11680       return oss.str();
11681     }
11682   else
11683     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11684 }
11685
11686 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11687 {
11688   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11689     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11690   else
11691     return INTERP_KERNEL::NORM_ERROR;
11692 }
11693
11694 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11695 {
11696   lgth=_conn_lgth;
11697   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11698     return _conn;
11699   else
11700     return 0;
11701 }