Salome HOME
MEDCoupling API renaming - stage #2
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
30 #include "BBTree.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
44
45 #include <sstream>
46 #include <fstream>
47 #include <numeric>
48 #include <cstring>
49 #include <limits>
50 #include <list>
51
52 using namespace MEDCoupling;
53
54 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
55
56 /// @cond INTERNAL
57 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
58 /// @endcond
59
60 MEDCouplingUMesh *MEDCouplingUMesh::New()
61 {
62   return new MEDCouplingUMesh;
63 }
64
65 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
66 {
67   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
68   ret->setName(meshName);
69   ret->setMeshDimension(meshDim);
70   return ret;
71 }
72
73 /*!
74  * Returns a new MEDCouplingUMesh which is a full copy of \a this one. No data is shared
75  * between \a this and the new mesh.
76  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
77  *          delete this mesh using decrRef() as it is no more needed. 
78  */
79 MEDCouplingUMesh *MEDCouplingUMesh::deepCopy() const
80 {
81   return clone(true);
82 }
83
84
85 /*!
86  * Returns a new MEDCouplingUMesh which is a copy of \a this one.
87  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
88  * this mesh are shared by the new mesh.
89  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
90  *          delete this mesh using decrRef() as it is no more needed. 
91  */
92 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
93 {
94   return new MEDCouplingUMesh(*this,recDeepCpy);
95 }
96
97 /*!
98  * This method behaves mostly like MEDCouplingUMesh::deepCopy method, except that only nodal connectivity arrays are deeply copied.
99  * The coordinates are shared between \a this and the returned instance.
100  * 
101  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
102  * \sa MEDCouplingUMesh::deepCopy
103  */
104 MEDCouplingUMesh *MEDCouplingUMesh::deepCopyConnectivityOnly() const
105 {
106   checkConnectivityFullyDefined();
107   MCAuto<MEDCouplingUMesh> ret=clone(false);
108   MCAuto<DataArrayInt> c(getNodalConnectivity()->deepCopy()),ci(getNodalConnectivityIndex()->deepCopy());
109   ret->setConnectivity(c,ci);
110   return ret.retn();
111 }
112
113 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
114 {
115   if(!other)
116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
117   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
118   if(!otherC)
119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
120   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
121   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
122 }
123
124 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
125 {
126   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
127   return ret;
128 }
129
130 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
131 {
132   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
133   ret.push_back(_nodal_connec);
134   ret.push_back(_nodal_connec_index);
135   return ret;
136 }
137
138 void MEDCouplingUMesh::updateTime() const
139 {
140   MEDCouplingPointSet::updateTime();
141   if(_nodal_connec)
142     {
143       updateTimeWith(*_nodal_connec);
144     }
145   if(_nodal_connec_index)
146     {
147       updateTimeWith(*_nodal_connec_index);
148     }
149 }
150
151 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
152 {
153 }
154
155 /*!
156  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
157  * then \a this mesh is most probably is writable, exchangeable and available for most
158  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
159  * this method to check that all is in order with \a this mesh.
160  *  \throw If the mesh dimension is not set.
161  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
162  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
163  *  \throw If the connectivity data array has more than one component.
164  *  \throw If the connectivity data array has a named component.
165  *  \throw If the connectivity index data array has more than one component.
166  *  \throw If the connectivity index data array has a named component.
167  */
168 void MEDCouplingUMesh::checkConsistencyLight() const
169 {
170   if(_mesh_dim<-1)
171     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
172   if(_mesh_dim!=-1)
173     MEDCouplingPointSet::checkConsistencyLight();
174   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
175     {
176       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
177         {
178           std::ostringstream message;
179           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
180           throw INTERP_KERNEL::Exception(message.str().c_str());
181         }
182     }
183   if(_nodal_connec)
184     {
185       if(_nodal_connec->getNumberOfComponents()!=1)
186         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
187       if(_nodal_connec->getInfoOnComponent(0)!="")
188         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
189     }
190   else
191     if(_mesh_dim!=-1)
192       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
193   if(_nodal_connec_index)
194     {
195       if(_nodal_connec_index->getNumberOfComponents()!=1)
196         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
197       if(_nodal_connec_index->getInfoOnComponent(0)!="")
198         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
199     }
200   else
201     if(_mesh_dim!=-1)
202       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
203 }
204
205 /*!
206  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
207  * then \a this mesh is most probably is writable, exchangeable and available for all
208  * algorithms. <br> In addition to the checks performed by checkConsistencyLight(), this
209  * method thoroughly checks the nodal connectivity.
210  *  \param [in] eps - a not used parameter.
211  *  \throw If the mesh dimension is not set.
212  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
213  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
214  *  \throw If the connectivity data array has more than one component.
215  *  \throw If the connectivity data array has a named component.
216  *  \throw If the connectivity index data array has more than one component.
217  *  \throw If the connectivity index data array has a named component.
218  *  \throw If number of nodes defining an element does not correspond to the type of element.
219  *  \throw If the nodal connectivity includes an invalid node id.
220  */
221 void MEDCouplingUMesh::checkConsistency(double eps) const
222 {
223   checkConsistencyLight();
224   if(_mesh_dim==-1)
225     return ;
226   int meshDim=getMeshDimension();
227   int nbOfNodes=getNumberOfNodes();
228   int nbOfCells=getNumberOfCells();
229   const int *ptr=_nodal_connec->getConstPointer();
230   const int *ptrI=_nodal_connec_index->getConstPointer();
231   for(int i=0;i<nbOfCells;i++)
232     {
233       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
234       if((int)cm.getDimension()!=meshDim)
235         {
236           std::ostringstream oss;
237           oss << "MEDCouplingUMesh::checkConsistency : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
238           throw INTERP_KERNEL::Exception(oss.str().c_str());
239         }
240       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
241       if(!cm.isDynamic())
242         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
243           {
244             std::ostringstream oss;
245             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
246             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
247             throw INTERP_KERNEL::Exception(oss.str().c_str());
248           }
249       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
250         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
251           {
252             std::ostringstream oss;
253             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
254             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
255             throw INTERP_KERNEL::Exception(oss.str().c_str());
256           }
257       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
258         {
259           int nodeId=*w;
260           if(nodeId>=0)
261             {
262               if(nodeId>=nbOfNodes)
263                 {
264                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
265                   throw INTERP_KERNEL::Exception(oss.str().c_str());
266                 }
267             }
268           else if(nodeId<-1)
269             {
270               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
271               throw INTERP_KERNEL::Exception(oss.str().c_str());
272             }
273           else
274             {
275               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
276                 {
277                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
278                   throw INTERP_KERNEL::Exception(oss.str().c_str());
279                 }
280             }
281         }
282     }
283 }
284
285 /*!
286  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
287  * elements contained in the mesh. For more info on the mesh dimension see
288  * \ref MEDCouplingUMeshPage.
289  *  \param [in] meshDim - a new mesh dimension.
290  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
291  */
292 void MEDCouplingUMesh::setMeshDimension(int meshDim)
293 {
294   if(meshDim<-1 || meshDim>3)
295     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
296   _mesh_dim=meshDim;
297   declareAsNew();
298 }
299
300 /*!
301  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
302  * the less will the library need to reallocate memory. If the number of cells to be inserted is not known simply put 0 to this parameter.
303  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
304  *
305  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
306  *
307  *  \if ENABLE_EXAMPLES
308  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
309  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
310  *  \endif
311  */
312 void MEDCouplingUMesh::allocateCells(int nbOfCells)
313 {
314   if(nbOfCells<0)
315     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
316   if(_nodal_connec_index)
317     {
318       _nodal_connec_index->decrRef();
319     }
320   if(_nodal_connec)
321     {
322       _nodal_connec->decrRef();
323     }
324   _nodal_connec_index=DataArrayInt::New();
325   _nodal_connec_index->reserve(nbOfCells+1);
326   _nodal_connec_index->pushBackSilent(0);
327   _nodal_connec=DataArrayInt::New();
328   _nodal_connec->reserve(2*nbOfCells);
329   _types.clear();
330   declareAsNew();
331 }
332
333 /*!
334  * Appends a cell to the connectivity array. For deeper understanding what is
335  * happening see \ref MEDCouplingUMeshNodalConnectivity.
336  *  \param [in] type - type of cell to add.
337  *  \param [in] size - number of nodes constituting this cell.
338  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
339  * 
340  *  \if ENABLE_EXAMPLES
341  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
342  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
343  *  \endif
344  */
345 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
346 {
347   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
348   if(_nodal_connec_index==0)
349     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
350   if((int)cm.getDimension()==_mesh_dim)
351     {
352       if(!cm.isDynamic())
353         if(size!=(int)cm.getNumberOfNodes())
354           {
355             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
356             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
357             throw INTERP_KERNEL::Exception(oss.str().c_str());
358           }
359       int idx=_nodal_connec_index->back();
360       int val=idx+size+1;
361       _nodal_connec_index->pushBackSilent(val);
362       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
363       _types.insert(type);
364     }
365   else
366     {
367       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
368       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
369       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
370       throw INTERP_KERNEL::Exception(oss.str().c_str());
371     }
372 }
373
374 /*!
375  * Compacts data arrays to release unused memory. This method is to be called after
376  * finishing cell insertion using \a this->insertNextCell().
377  * 
378  *  \if ENABLE_EXAMPLES
379  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
380  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
381  *  \endif
382  */
383 void MEDCouplingUMesh::finishInsertingCells()
384 {
385   _nodal_connec->pack();
386   _nodal_connec_index->pack();
387   _nodal_connec->declareAsNew();
388   _nodal_connec_index->declareAsNew();
389   updateTime();
390 }
391
392 /*!
393  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
394  * Useful for python users.
395  */
396 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
397 {
398   return new MEDCouplingUMeshCellIterator(this);
399 }
400
401 /*!
402  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
403  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
404  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
405  * Useful for python users.
406  */
407 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
408 {
409   if(!checkConsecutiveCellTypes())
410     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
411   return new MEDCouplingUMeshCellByTypeEntry(this);
412 }
413
414 /*!
415  * Returns a set of all cell types available in \a this mesh.
416  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
417  * \warning this method does not throw any exception even if \a this is not defined.
418  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
419  */
420 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
421 {
422   return _types;
423 }
424
425 /*!
426  * This method returns the sorted list of geometric types in \a this.
427  * 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
428  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
429  *
430  * \throw if connectivity in \a this is not correctly defined.
431  *  
432  * \sa MEDCouplingMesh::getAllGeoTypes
433  */
434 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
435 {
436   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
437   checkConnectivityFullyDefined();
438   int nbOfCells(getNumberOfCells());
439   if(nbOfCells==0)
440     return ret;
441   if(getNodalConnectivityArrayLen()<1)
442     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
443   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
444   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
445   for(int i=1;i<nbOfCells;i++,ci++)
446     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
447       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
448   return ret;
449 }
450
451 /*!
452  * This method is a method that compares \a this and \a other.
453  * This method compares \b all attributes, even names and component names.
454  */
455 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
456 {
457   if(!other)
458     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
459   std::ostringstream oss; oss.precision(15);
460   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
461   if(!otherC)
462     {
463       reason="mesh given in input is not castable in MEDCouplingUMesh !";
464       return false;
465     }
466   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
467     return false;
468   if(_mesh_dim!=otherC->_mesh_dim)
469     {
470       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
471       reason=oss.str();
472       return false;
473     }
474   if(_types!=otherC->_types)
475     {
476       oss << "umesh geometric type mismatch :\nThis geometric types are :";
477       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
478         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
479       oss << "\nOther geometric types are :";
480       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
481         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
482       reason=oss.str();
483       return false;
484     }
485   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
486     if(_nodal_connec==0 || otherC->_nodal_connec==0)
487       {
488         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
489         return false;
490       }
491   if(_nodal_connec!=otherC->_nodal_connec)
492     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
493       {
494         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
495         return false;
496       }
497   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
498     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
499       {
500         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
501         return false;
502       }
503   if(_nodal_connec_index!=otherC->_nodal_connec_index)
504     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
505       {
506         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
507         return false;
508       }
509   return true;
510 }
511
512 /*!
513  * Checks if data arrays of this mesh (node coordinates, nodal
514  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
515  * not considered.
516  *  \param [in] other - the mesh to compare with.
517  *  \param [in] prec - precision value used to compare node coordinates.
518  *  \return bool - \a true if the two meshes are same.
519  */
520 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
521 {
522   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
523   if(!otherC)
524     return false;
525   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
526     return false;
527   if(_mesh_dim!=otherC->_mesh_dim)
528     return false;
529   if(_types!=otherC->_types)
530     return false;
531   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
532     if(_nodal_connec==0 || otherC->_nodal_connec==0)
533       return false;
534   if(_nodal_connec!=otherC->_nodal_connec)
535     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
536       return false;
537   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
538     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
539       return false;
540   if(_nodal_connec_index!=otherC->_nodal_connec_index)
541     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
542       return false;
543   return true;
544 }
545
546 /*!
547  * Checks if \a this and \a other meshes are geometrically equivalent with high
548  * probability, else an exception is thrown. The meshes are considered equivalent if
549  * (1) meshes contain the same number of nodes and the same number of elements of the
550  * same types (2) three cells of the two meshes (first, last and middle) are based
551  * on coincident nodes (with a specified precision).
552  *  \param [in] other - the mesh to compare with.
553  *  \param [in] prec - the precision used to compare nodes of the two meshes.
554  *  \throw If the two meshes do not match.
555  */
556 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
557 {
558   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
559   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
560   if(!otherC)
561     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
562 }
563
564 /*!
565  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
566  * cells each node belongs to.
567  * \warning For speed reasons, this method does not check if node ids in the nodal
568  *          connectivity correspond to the size of node coordinates array.
569  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
570  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
571  *        dividing cell ids in \a revNodal into groups each referring to one
572  *        node. Its every element (except the last one) is an index pointing to the
573  *         first id of a group of cells. For example cells sharing the node #1 are 
574  *        described by following range of indices: 
575  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
576  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
577  *        Number of cells sharing the *i*-th node is
578  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
579  * \throw If the coordinates array is not set.
580  * \throw If the nodal connectivity of cells is not defined.
581  * 
582  * \if ENABLE_EXAMPLES
583  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
584  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
585  * \endif
586  */
587 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
588 {
589   checkFullyDefined();
590   int nbOfNodes=getNumberOfNodes();
591   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
592   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
593   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
594   const int *conn=_nodal_connec->getConstPointer();
595   const int *connIndex=_nodal_connec_index->getConstPointer();
596   int nbOfCells=getNumberOfCells();
597   int nbOfEltsInRevNodal=0;
598   for(int eltId=0;eltId<nbOfCells;eltId++)
599     {
600       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
601       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
602       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
603         if(*iter>=0)//for polyhedrons
604           {
605             nbOfEltsInRevNodal++;
606             revNodalIndxPtr[(*iter)+1]++;
607           }
608     }
609   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
610   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
611   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
612   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
613   for(int eltId=0;eltId<nbOfCells;eltId++)
614     {
615       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
616       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
617       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
618         if(*iter>=0)//for polyhedrons
619           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
620     }
621 }
622
623 /// @cond INTERNAL
624
625 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
626 {
627   return id;
628 }
629
630 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
631 {
632   if(!compute)
633     return id+1;
634   else
635     {
636       if(cm.getOrientationStatus(nb,conn1,conn2))
637         return id+1;
638       else
639         return -(id+1);
640     }
641 }
642
643 class MinusOneSonsGenerator
644 {
645 public:
646   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
647   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
648   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
649   static const int DELTA=1;
650 private:
651   const INTERP_KERNEL::CellModel& _cm;
652 };
653
654 class MinusOneSonsGeneratorBiQuadratic
655 {
656 public:
657   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
658   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
659   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
660   static const int DELTA=1;
661 private:
662   const INTERP_KERNEL::CellModel& _cm;
663 };
664
665 class MinusTwoSonsGenerator
666 {
667 public:
668   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
669   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
670   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
671   static const int DELTA=2;
672 private:
673   const INTERP_KERNEL::CellModel& _cm;
674 };
675
676 /// @endcond
677
678 /*!
679  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
680  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
681  * describing correspondence between cells of \a this and the result meshes are
682  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
683  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
684  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
685  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
686  * \warning For speed reasons, this method does not check if node ids in the nodal
687  *          connectivity correspond to the size of node coordinates array.
688  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
689  *          to write this mesh to the MED file, its cells must be sorted using
690  *          sortCellsInMEDFileFrmt().
691  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
692  *         each cell of \a this mesh.
693  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
694  *        dividing cell ids in \a desc into groups each referring to one
695  *        cell of \a this mesh. Its every element (except the last one) is an index
696  *        pointing to the first id of a group of cells. For example cells of the
697  *        result mesh bounding the cell #1 of \a this mesh are described by following
698  *        range of indices:
699  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
700  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
701  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
702  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
703  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
704  *         by each cell of the result mesh.
705  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
706  *        in the result mesh,
707  *        dividing cell ids in \a revDesc into groups each referring to one
708  *        cell of the result mesh the same way as \a descIndx divides \a desc.
709  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
710  *        delete this mesh using decrRef() as it is no more needed.
711  *  \throw If the coordinates array is not set.
712  *  \throw If the nodal connectivity of cells is node defined.
713  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
714  *         revDescIndx == NULL.
715  * 
716  *  \if ENABLE_EXAMPLES
717  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
718  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
719  *  \endif
720  * \sa buildDescendingConnectivity2()
721  */
722 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
723 {
724   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
725 }
726
727 /*!
728  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
729  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
730  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
731  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
732  * \sa MEDCouplingUMesh::buildDescendingConnectivity
733  */
734 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
735 {
736   checkFullyDefined();
737   if(getMeshDimension()!=3)
738     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
739   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
740 }
741
742 /*!
743  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
744  * this->getMeshDimension(), that bound cells of \a this mesh. In
745  * addition arrays describing correspondence between cells of \a this and the result
746  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
747  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
748  *  mesh. This method differs from buildDescendingConnectivity() in that apart
749  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
750  * result meshes. So a positive id means that order of nodes in corresponding cells
751  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
752  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
753  * i.e. cell ids are one-based.
754  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
755  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
756  * \warning For speed reasons, this method does not check if node ids in the nodal
757  *          connectivity correspond to the size of node coordinates array.
758  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
759  *          to write this mesh to the MED file, its cells must be sorted using
760  *          sortCellsInMEDFileFrmt().
761  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
762  *         each cell of \a this mesh.
763  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
764  *        dividing cell ids in \a desc into groups each referring to one
765  *        cell of \a this mesh. Its every element (except the last one) is an index
766  *        pointing to the first id of a group of cells. For example cells of the
767  *        result mesh bounding the cell #1 of \a this mesh are described by following
768  *        range of indices:
769  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
770  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
771  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
772  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
773  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
774  *         by each cell of the result mesh.
775  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
776  *        in the result mesh,
777  *        dividing cell ids in \a revDesc into groups each referring to one
778  *        cell of the result mesh the same way as \a descIndx divides \a desc.
779  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
780  *        shares the node coordinates array with \a this mesh. The caller is to
781  *        delete this mesh using decrRef() as it is no more needed.
782  *  \throw If the coordinates array is not set.
783  *  \throw If the nodal connectivity of cells is node defined.
784  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
785  *         revDescIndx == NULL.
786  * 
787  *  \if ENABLE_EXAMPLES
788  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
789  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
790  *  \endif
791  * \sa buildDescendingConnectivity()
792  */
793 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
794 {
795   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
796 }
797
798 /*!
799  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
800  * For speed reasons no check of this will be done. This method calls
801  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
802  * This method lists cell by cell in \b this which are its neighbors. To compute the result
803  * only connectivities are considered.
804  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
805  * The format of return is hence \ref numbering-indirect.
806  *
807  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
808  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
809  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
810  * is equal to the last values in \b neighborsIndx.
811  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
812  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
813  */
814 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
815 {
816   MCAuto<DataArrayInt> desc=DataArrayInt::New();
817   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
818   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
819   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
820   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
821   meshDM1=0;
822   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
823 }
824
825 /*!
826  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
827  * of MEDCouplingUMesh::computeNeighborsOfCells.
828  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
829  * 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 (\ref numbering-indirect) input params are
832  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
833  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
834  * are considered.
835  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
836  *
837  * \param [in] desc descending connectivity array.
838  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
839  * \param [in] revDesc reverse descending connectivity array.
840  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
841  * \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
842  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
843  * \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.
844  */
845 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
846                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
847 {
848   if(!desc || !descIndx || !revDesc || !revDescIndx)
849     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
850   const int *descPtr=desc->getConstPointer();
851   const int *descIPtr=descIndx->getConstPointer();
852   const int *revDescPtr=revDesc->getConstPointer();
853   const int *revDescIPtr=revDescIndx->getConstPointer();
854   //
855   int nbCells=descIndx->getNumberOfTuples()-1;
856   MCAuto<DataArrayInt> out0=DataArrayInt::New();
857   MCAuto<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
858   int *out1Ptr=out1->getPointer();
859   *out1Ptr++=0;
860   out0->reserve(desc->getNumberOfTuples());
861   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
862     {
863       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
864         {
865           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
866           s.erase(i);
867           out0->insertAtTheEnd(s.begin(),s.end());
868         }
869       *out1Ptr=out0->getNumberOfTuples();
870     }
871   neighbors=out0.retn();
872   neighborsIndx=out1.retn();
873 }
874
875 /*!
876  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
877  * For speed reasons no check of this will be done. This method calls
878  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
879  * This method lists node by node in \b this which are its neighbors. To compute the result
880  * only connectivities are considered.
881  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
882  *
883  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
884  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
885  * parameter allows to select the right part in this array (\ref numbering-indirect).
886  * The number of tuples is equal to the last values in \b neighborsIndx.
887  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
888  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
889  */
890 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
891 {
892   checkFullyDefined();
893   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
894   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
895   MCAuto<MEDCouplingUMesh> mesh1D;
896   switch(mdim)
897   {
898     case 3:
899       {
900         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
901         break;
902       }
903     case 2:
904       {
905         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
906         break;
907       }
908     case 1:
909       {
910         mesh1D=const_cast<MEDCouplingUMesh *>(this);
911         mesh1D->incrRef();
912         break;
913       }
914     default:
915       {
916         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
917       }
918   }
919   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
920   mesh1D->getReverseNodalConnectivity(desc,descIndx);
921   MCAuto<DataArrayInt> ret0(DataArrayInt::New());
922   ret0->alloc(desc->getNumberOfTuples(),1);
923   int *r0Pt(ret0->getPointer());
924   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
925   for(int i=0;i<nbNodes;i++,rni++)
926     {
927       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
928         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
929     }
930   neighbors=ret0.retn();
931   neighborsIdx=descIndx.retn();
932 }
933
934 /// @cond INTERNAL
935
936 /*!
937  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
938  * For speed reasons no check of this will be done.
939  */
940 template<class SonsGenerator>
941 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
942 {
943   if(!desc || !descIndx || !revDesc || !revDescIndx)
944     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
945   checkConnectivityFullyDefined();
946   int nbOfCells=getNumberOfCells();
947   int nbOfNodes=getNumberOfNodes();
948   MCAuto<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
949   int *revNodalIndxPtr=revNodalIndx->getPointer();
950   const int *conn=_nodal_connec->getConstPointer();
951   const int *connIndex=_nodal_connec_index->getConstPointer();
952   std::string name="Mesh constituent of "; name+=getName();
953   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
954   ret->setCoords(getCoords());
955   ret->allocateCells(2*nbOfCells);
956   descIndx->alloc(nbOfCells+1,1);
957   MCAuto<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
958   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
959   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
960     {
961       int pos=connIndex[eltId];
962       int posP1=connIndex[eltId+1];
963       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
964       SonsGenerator sg(cm);
965       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
966       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
967       for(unsigned i=0;i<nbOfSons;i++)
968         {
969           INTERP_KERNEL::NormalizedCellType cmsId;
970           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
971           for(unsigned k=0;k<nbOfNodesSon;k++)
972             if(tmp[k]>=0)
973               revNodalIndxPtr[tmp[k]+1]++;
974           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
975           revDesc2->pushBackSilent(eltId);
976         }
977       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
978     }
979   int nbOfCellsM1=ret->getNumberOfCells();
980   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
981   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
982   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
983   int *revNodalPtr=revNodal->getPointer();
984   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
985   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
986   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
987     {
988       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
989       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
990       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
991         if(*iter>=0)//for polyhedrons
992           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
993     }
994   //
995   DataArrayInt *commonCells=0,*commonCellsI=0;
996   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
997   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
998   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
999   int newNbOfCellsM1=-1;
1000   MCAuto<DataArrayInt> o2nM1=DataArrayInt::ConvertIndexArrayToO2N(nbOfCellsM1,commonCells->begin(),
1001                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1002   std::vector<bool> isImpacted(nbOfCellsM1,false);
1003   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1004     for(int work2=work[0];work2!=work[1];work2++)
1005       isImpacted[commonCellsPtr[work2]]=true;
1006   const int *o2nM1Ptr=o2nM1->getConstPointer();
1007   MCAuto<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1008   const int *n2oM1Ptr=n2oM1->getConstPointer();
1009   MCAuto<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1010   ret2->copyTinyInfoFrom(this);
1011   desc->alloc(descIndx->back(),1);
1012   int *descPtr=desc->getPointer();
1013   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1014   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1015     {
1016       if(!isImpacted[i])
1017         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1018       else
1019         {
1020           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1021             {
1022               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1023               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1024             }
1025           else
1026             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1027         }
1028     }
1029   revDesc->reserve(newNbOfCellsM1);
1030   revDescIndx->alloc(newNbOfCellsM1+1,1);
1031   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1032   const int *revDesc2Ptr=revDesc2->getConstPointer();
1033   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1034     {
1035       int oldCellIdM1=n2oM1Ptr[i];
1036       if(!isImpacted[oldCellIdM1])
1037         {
1038           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1039           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1040         }
1041       else
1042         {
1043           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1044             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1045           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1046           commonCellsIPtr++;
1047         }
1048     }
1049   //
1050   return ret2.retn();
1051 }
1052
1053 struct MEDCouplingAccVisit
1054 {
1055   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1056   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1057   int _new_nb_of_nodes;
1058 };
1059
1060 /// @endcond
1061
1062 /*!
1063  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1064  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1065  * array of cell ids. Pay attention that after conversion all algorithms work slower
1066  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1067  * conversion due presence of invalid ids in the array of cells to convert, as a
1068  * result \a this mesh contains some already converted elements. In this case the 2D
1069  * mesh remains valid but 3D mesh becomes \b inconsistent!
1070  *  \warning This method can significantly modify the order of geometric types in \a this,
1071  *          hence, to write this mesh to the MED file, its cells must be sorted using
1072  *          sortCellsInMEDFileFrmt().
1073  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1074  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1075  *         cellIdsToConvertBg.
1076  *  \throw If the coordinates array is not set.
1077  *  \throw If the nodal connectivity of cells is node defined.
1078  *  \throw If dimension of \a this mesh is not either 2 or 3.
1079  *
1080  *  \if ENABLE_EXAMPLES
1081  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1082  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1083  *  \endif
1084  */
1085 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1086 {
1087   checkFullyDefined();
1088   int dim=getMeshDimension();
1089   if(dim<2 || dim>3)
1090     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1091   int nbOfCells(getNumberOfCells());
1092   if(dim==2)
1093     {
1094       const int *connIndex=_nodal_connec_index->getConstPointer();
1095       int *conn=_nodal_connec->getPointer();
1096       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1097         {
1098           if(*iter>=0 && *iter<nbOfCells)
1099             {
1100               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1101               if(!cm.isQuadratic())
1102                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1103               else
1104                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1105             }
1106           else
1107             {
1108               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1109               oss << " in range [0," << nbOfCells << ") !";
1110               throw INTERP_KERNEL::Exception(oss.str().c_str());
1111             }
1112         }
1113     }
1114   else
1115     {
1116       int *connIndex(_nodal_connec_index->getPointer());
1117       const int *connOld(_nodal_connec->getConstPointer());
1118       MCAuto<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1119       std::vector<bool> toBeDone(nbOfCells,false);
1120       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1121         {
1122           if(*iter>=0 && *iter<nbOfCells)
1123             toBeDone[*iter]=true;
1124           else
1125             {
1126               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1127               oss << " in range [0," << nbOfCells << ") !";
1128               throw INTERP_KERNEL::Exception(oss.str().c_str());
1129             }
1130         }
1131       for(int cellId=0;cellId<nbOfCells;cellId++)
1132         {
1133           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1134           int lgthOld(posP1-pos-1);
1135           if(toBeDone[cellId])
1136             {
1137               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1138               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1139               int *tmp(new int[nbOfFaces*lgthOld+1]);
1140               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1141               for(unsigned j=0;j<nbOfFaces;j++)
1142                 {
1143                   INTERP_KERNEL::NormalizedCellType type;
1144                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1145                   work+=offset;
1146                   *work++=-1;
1147                 }
1148               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1149               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1150               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1151               delete [] tmp;
1152             }
1153           else
1154             {
1155               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1156               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1157             }
1158         }
1159       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1160     }
1161   computeTypes();
1162 }
1163
1164 /*!
1165  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1166  * polyhedrons (if \a this is a 3D mesh).
1167  *  \warning As this method is purely for user-friendliness and no optimization is
1168  *          done to avoid construction of a useless vector, this method can be costly
1169  *          in memory.
1170  *  \throw If the coordinates array is not set.
1171  *  \throw If the nodal connectivity of cells is node defined.
1172  *  \throw If dimension of \a this mesh is not either 2 or 3.
1173  */
1174 void MEDCouplingUMesh::convertAllToPoly()
1175 {
1176   int nbOfCells=getNumberOfCells();
1177   std::vector<int> cellIds(nbOfCells);
1178   for(int i=0;i<nbOfCells;i++)
1179     cellIds[i]=i;
1180   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1181 }
1182
1183 /*!
1184  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1185  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1186  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1187  * base facet of the volume and the second half of nodes describes an opposite facet
1188  * having the same number of nodes as the base one. This method converts such
1189  * connectivity to a valid polyhedral format where connectivity of each facet is
1190  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1191  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1192  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1193  * a correct orientation of the first facet of a polyhedron, else orientation of a
1194  * corrected cell is reverse.<br>
1195  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1196  * it releases the user from boring description of polyhedra connectivity in the valid
1197  * format.
1198  *  \throw If \a this->getMeshDimension() != 3.
1199  *  \throw If \a this->getSpaceDimension() != 3.
1200  *  \throw If the nodal connectivity of cells is not defined.
1201  *  \throw If the coordinates array is not set.
1202  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1203  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1204  *
1205  *  \if ENABLE_EXAMPLES
1206  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1207  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1208  *  \endif
1209  */
1210 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1211 {
1212   checkFullyDefined();
1213   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1214     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1215   int nbOfCells=getNumberOfCells();
1216   MCAuto<DataArrayInt> newCi=DataArrayInt::New();
1217   newCi->alloc(nbOfCells+1,1);
1218   int *newci=newCi->getPointer();
1219   const int *ci=_nodal_connec_index->getConstPointer();
1220   const int *c=_nodal_connec->getConstPointer();
1221   newci[0]=0;
1222   for(int i=0;i<nbOfCells;i++)
1223     {
1224       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1225       if(type==INTERP_KERNEL::NORM_POLYHED)
1226         {
1227           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1228             {
1229               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1230               throw INTERP_KERNEL::Exception(oss.str().c_str());
1231             }
1232           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1233           if(n2%2!=0)
1234             {
1235               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 !";
1236               throw INTERP_KERNEL::Exception(oss.str().c_str());
1237             }
1238           int n1=(int)(n2/2);
1239           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)
1240         }
1241       else
1242         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1243     }
1244   MCAuto<DataArrayInt> newC=DataArrayInt::New();
1245   newC->alloc(newci[nbOfCells],1);
1246   int *newc=newC->getPointer();
1247   for(int i=0;i<nbOfCells;i++)
1248     {
1249       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1250       if(type==INTERP_KERNEL::NORM_POLYHED)
1251         {
1252           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1253           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1254           *newc++=-1;
1255           for(std::size_t j=0;j<n1;j++)
1256             {
1257               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1258               newc[n1+5*j]=-1;
1259               newc[n1+5*j+1]=c[ci[i]+1+j];
1260               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1261               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1262               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1263             }
1264           newc+=n1*6;
1265         }
1266       else
1267         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1268     }
1269   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1270   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1271 }
1272
1273
1274 /*!
1275  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1276  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1277  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1278  *          to write this mesh to the MED file, its cells must be sorted using
1279  *          sortCellsInMEDFileFrmt().
1280  * \return \c true if at least one cell has been converted, \c false else. In the
1281  *         last case the nodal connectivity remains unchanged.
1282  * \throw If the coordinates array is not set.
1283  * \throw If the nodal connectivity of cells is not defined.
1284  * \throw If \a this->getMeshDimension() < 0.
1285  */
1286 bool MEDCouplingUMesh::unPolyze()
1287 {
1288   checkFullyDefined();
1289   int mdim=getMeshDimension();
1290   if(mdim<0)
1291     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1292   if(mdim<=1)
1293     return false;
1294   int nbOfCells=getNumberOfCells();
1295   if(nbOfCells<1)
1296     return false;
1297   int initMeshLgth=getNodalConnectivityArrayLen();
1298   int *conn=_nodal_connec->getPointer();
1299   int *index=_nodal_connec_index->getPointer();
1300   int posOfCurCell=0;
1301   int newPos=0;
1302   int lgthOfCurCell;
1303   bool ret=false;
1304   for(int i=0;i<nbOfCells;i++)
1305     {
1306       lgthOfCurCell=index[i+1]-posOfCurCell;
1307       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1308       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1309       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1310       int newLgth;
1311       if(cm.isDynamic())
1312         {
1313           switch(cm.getDimension())
1314           {
1315             case 2:
1316               {
1317                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1318                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1319                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1320                 break;
1321               }
1322             case 3:
1323               {
1324                 int nbOfFaces,lgthOfPolyhConn;
1325                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1326                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1327                 break;
1328               }
1329             case 1:
1330               {
1331                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1332                 break;
1333               }
1334           }
1335           ret=ret || (newType!=type);
1336           conn[newPos]=newType;
1337           newPos+=newLgth+1;
1338           posOfCurCell=index[i+1];
1339           index[i+1]=newPos;
1340         }
1341       else
1342         {
1343           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1344           newPos+=lgthOfCurCell;
1345           posOfCurCell+=lgthOfCurCell;
1346           index[i+1]=newPos;
1347         }
1348     }
1349   if(newPos!=initMeshLgth)
1350     _nodal_connec->reAlloc(newPos);
1351   if(ret)
1352     computeTypes();
1353   return ret;
1354 }
1355
1356 /*!
1357  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1358  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1359  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1360  *
1361  * \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 
1362  *             precision.
1363  */
1364 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1365 {
1366   checkFullyDefined();
1367   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1369   MCAuto<DataArrayDouble> coords=getCoords()->deepCopy();
1370   coords->recenterForMaxPrecision(eps);
1371   //
1372   int nbOfCells=getNumberOfCells();
1373   const int *conn=_nodal_connec->getConstPointer();
1374   const int *index=_nodal_connec_index->getConstPointer();
1375   MCAuto<DataArrayInt> connINew=DataArrayInt::New();
1376   connINew->alloc(nbOfCells+1,1);
1377   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1378   MCAuto<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1379   bool changed=false;
1380   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1381     {
1382       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1383         {
1384           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1385           changed=true;
1386         }
1387       else
1388         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1389       *connINewPtr=connNew->getNumberOfTuples();
1390     }
1391   if(changed)
1392     setConnectivity(connNew,connINew,false);
1393 }
1394
1395 /*!
1396  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1397  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1398  * the format of the returned DataArrayInt instance.
1399  * 
1400  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1401  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1402  */
1403 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1404 {
1405   checkConnectivityFullyDefined();
1406   int nbOfCells=getNumberOfCells();
1407   const int *connIndex=_nodal_connec_index->getConstPointer();
1408   const int *conn=_nodal_connec->getConstPointer();
1409   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1410   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1411   std::vector<bool> retS(maxElt,false);
1412   for(int i=0;i<nbOfCells;i++)
1413     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1414       if(conn[j]>=0)
1415         retS[conn[j]]=true;
1416   int sz=0;
1417   for(int i=0;i<maxElt;i++)
1418     if(retS[i])
1419       sz++;
1420   DataArrayInt *ret=DataArrayInt::New();
1421   ret->alloc(sz,1);
1422   int *retPtr=ret->getPointer();
1423   for(int i=0;i<maxElt;i++)
1424     if(retS[i])
1425       *retPtr++=i;
1426   return ret;
1427 }
1428
1429 /*!
1430  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1431  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1432  */
1433 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1434 {
1435   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1436   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1437   for(int i=0;i<nbOfCells;i++)
1438     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1439       if(conn[j]>=0)
1440         {
1441           if(conn[j]<nbOfNodes)
1442             nodeIdsInUse[conn[j]]=true;
1443           else
1444             {
1445               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1446               throw INTERP_KERNEL::Exception(oss.str().c_str());
1447             }
1448         }
1449 }
1450
1451 /*!
1452  * Finds nodes not used in any cell and returns an array giving a new id to every node
1453  * by excluding the unused nodes, for which the array holds -1. The result array is
1454  * a mapping in "Old to New" mode. 
1455  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1456  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1457  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1458  *          if the node is unused or a new id else. The caller is to delete this
1459  *          array using decrRef() as it is no more needed.  
1460  *  \throw If the coordinates array is not set.
1461  *  \throw If the nodal connectivity of cells is not defined.
1462  *  \throw If the nodal connectivity includes an invalid id.
1463  *
1464  *  \if ENABLE_EXAMPLES
1465  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1466  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1467  *  \endif
1468  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1469  */
1470 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1471 {
1472   nbrOfNodesInUse=-1;
1473   int nbOfNodes(getNumberOfNodes());
1474   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1475   ret->alloc(nbOfNodes,1);
1476   int *traducer=ret->getPointer();
1477   std::fill(traducer,traducer+nbOfNodes,-1);
1478   int nbOfCells=getNumberOfCells();
1479   const int *connIndex=_nodal_connec_index->getConstPointer();
1480   const int *conn=_nodal_connec->getConstPointer();
1481   for(int i=0;i<nbOfCells;i++)
1482     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1483       if(conn[j]>=0)
1484         {
1485           if(conn[j]<nbOfNodes)
1486             traducer[conn[j]]=1;
1487           else
1488             {
1489               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1490               throw INTERP_KERNEL::Exception(oss.str().c_str());
1491             }
1492         }
1493   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1494   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1495   return ret.retn();
1496 }
1497
1498 /*!
1499  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1500  * For each cell in \b this the number of nodes constituting cell is computed.
1501  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1502  * So for pohyhedrons some nodes can be counted several times in the returned result.
1503  * 
1504  * \return a newly allocated array
1505  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1506  */
1507 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1508 {
1509   checkConnectivityFullyDefined();
1510   int nbOfCells=getNumberOfCells();
1511   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1512   ret->alloc(nbOfCells,1);
1513   int *retPtr=ret->getPointer();
1514   const int *conn=getNodalConnectivity()->getConstPointer();
1515   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1516   for(int i=0;i<nbOfCells;i++,retPtr++)
1517     {
1518       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1519         *retPtr=connI[i+1]-connI[i]-1;
1520       else
1521         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1522     }
1523   return ret.retn();
1524 }
1525
1526 /*!
1527  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1528  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1529  *
1530  * \return DataArrayInt * - new object to be deallocated by the caller.
1531  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1532  */
1533 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1534 {
1535   checkConnectivityFullyDefined();
1536   int nbOfCells=getNumberOfCells();
1537   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1538   ret->alloc(nbOfCells,1);
1539   int *retPtr=ret->getPointer();
1540   const int *conn=getNodalConnectivity()->getConstPointer();
1541   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1542   for(int i=0;i<nbOfCells;i++,retPtr++)
1543     {
1544       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1545       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1546         *retPtr=(int)s.size();
1547       else
1548         {
1549           s.erase(-1);
1550           *retPtr=(int)s.size();
1551         }
1552     }
1553   return ret.retn();
1554 }
1555
1556 /*!
1557  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1558  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1559  * 
1560  * \return a newly allocated array
1561  */
1562 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1563 {
1564   checkConnectivityFullyDefined();
1565   int nbOfCells=getNumberOfCells();
1566   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1567   ret->alloc(nbOfCells,1);
1568   int *retPtr=ret->getPointer();
1569   const int *conn=getNodalConnectivity()->getConstPointer();
1570   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1571   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1572     {
1573       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1574       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1575     }
1576   return ret.retn();
1577 }
1578
1579 /*!
1580  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1581  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1582  * array mean that the corresponding old node is no more used. 
1583  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1584  *           this->getNumberOfNodes() before call of this method. The caller is to
1585  *           delete this array using decrRef() as it is no more needed. 
1586  *  \throw If the coordinates array is not set.
1587  *  \throw If the nodal connectivity of cells is not defined.
1588  *  \throw If the nodal connectivity includes an invalid id.
1589  *  \sa areAllNodesFetched
1590  *
1591  *  \if ENABLE_EXAMPLES
1592  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1593  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1594  *  \endif
1595  */
1596 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1597 {
1598   return MEDCouplingPointSet::zipCoordsTraducer();
1599 }
1600
1601 /*!
1602  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1603  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1604  */
1605 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1606 {
1607   switch(compType)
1608   {
1609     case 0:
1610       return AreCellsEqualPolicy0(conn,connI,cell1,cell2);
1611     case 1:
1612       return AreCellsEqualPolicy1(conn,connI,cell1,cell2);
1613     case 2:
1614       return AreCellsEqualPolicy2(conn,connI,cell1,cell2);
1615     case 3:
1616       return AreCellsEqualPolicy2NoType(conn,connI,cell1,cell2);
1617     case 7:
1618       return AreCellsEqualPolicy7(conn,connI,cell1,cell2);
1619   }
1620   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1621 }
1622
1623 /*!
1624  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1625  */
1626 int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, int cell1, int cell2)
1627 {
1628   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1629     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1630   return 0;
1631 }
1632
1633 /*!
1634  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1635  */
1636 int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, int cell1, int cell2)
1637 {
1638   int sz=connI[cell1+1]-connI[cell1];
1639   if(sz==connI[cell2+1]-connI[cell2])
1640     {
1641       if(conn[connI[cell1]]==conn[connI[cell2]])
1642         {
1643           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1644           unsigned dim=cm.getDimension();
1645           if(dim!=3)
1646             {
1647               if(dim!=1)
1648                 {
1649                   int sz1=2*(sz-1);
1650                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1651                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1652                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1653                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1654                   return work!=tmp+sz1?1:0;
1655                 }
1656               else
1657                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1658             }
1659           else
1660             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy1 : not implemented yet for meshdim == 3 !");
1661         }
1662     }
1663   return 0;
1664 }
1665
1666 /*!
1667  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1668  */
1669 int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, int cell1, int cell2)
1670 {
1671   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1672     {
1673       if(conn[connI[cell1]]==conn[connI[cell2]])
1674         {
1675           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1676           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1677           return s1==s2?1:0;
1678         }
1679     }
1680   return 0;
1681 }
1682
1683 /*!
1684  * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account !
1685  */
1686 int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *connI, int cell1, int cell2)
1687 {
1688   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1689     {
1690       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1691       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1692       return s1==s2?1:0;
1693     }
1694   return 0;
1695 }
1696
1697 /*!
1698  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1699  */
1700 int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, int cell1, int cell2)
1701 {
1702   int sz=connI[cell1+1]-connI[cell1];
1703   if(sz==connI[cell2+1]-connI[cell2])
1704     {
1705       if(conn[connI[cell1]]==conn[connI[cell2]])
1706         {
1707           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1708           unsigned dim=cm.getDimension();
1709           if(dim!=3)
1710             {
1711               if(dim!=1)
1712                 {
1713                   int sz1=2*(sz-1);
1714                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1715                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1716                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1717                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1718                   if(work!=tmp+sz1)
1719                     return 1;
1720                   else
1721                     {
1722                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1723                       std::reverse_iterator<int *> it2((int *)tmp);
1724                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1725                         return 2;
1726                       else
1727                         return 0;
1728                     }
1729
1730                   return work!=tmp+sz1?1:0;
1731                 }
1732               else
1733                 {//case of SEG2 and SEG3
1734                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1735                     return 1;
1736                   if(!cm.isQuadratic())
1737                     {
1738                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1739                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1740                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1741                         return 2;
1742                       return 0;
1743                     }
1744                   else
1745                     {
1746                       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])
1747                         return 2;
1748                       return 0;
1749                     }
1750                 }
1751             }
1752           else
1753             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy7 : not implemented yet for meshdim == 3 !");
1754         }
1755     }
1756   return 0;
1757 }
1758
1759 /*!
1760  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1761  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1762  * and result remains unchanged.
1763  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1764  * If in 'candidates' pool -1 value is considered as an empty value.
1765  * WARNING this method returns only ONE set of result !
1766  */
1767 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1768 {
1769   if(candidates.size()<1)
1770     return false;
1771   bool ret=false;
1772   std::vector<int>::const_iterator iter=candidates.begin();
1773   int start=(*iter++);
1774   for(;iter!=candidates.end();iter++)
1775     {
1776       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1777       if(status!=0)
1778         {
1779           if(!ret)
1780             {
1781               result->pushBackSilent(start);
1782               ret=true;
1783             }
1784           if(status==1)
1785             result->pushBackSilent(*iter);
1786           else
1787             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1788         }
1789     }
1790   return ret;
1791 }
1792
1793 /*!
1794  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1795  * by \a compType.
1796  * This method keeps the coordiantes of \a this. This method is time consuming.
1797  *
1798  * \param [in] compType input specifying the technique used to compare cells each other.
1799  *   - 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.
1800  *   - 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)
1801  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1802  *   - 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
1803  * can be used for users not sensitive to orientation of cell
1804  * \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.
1805  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1806  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1807  * \return the correspondance array old to new in a newly allocated array.
1808  * 
1809  */
1810 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1811 {
1812   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1813   getReverseNodalConnectivity(revNodal,revNodalI);
1814   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1815 }
1816
1817 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1818                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1819 {
1820   MCAuto<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1821   int nbOfCells=nodalI->getNumberOfTuples()-1;
1822   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1823   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1824   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1825   std::vector<bool> isFetched(nbOfCells,false);
1826   if(startCellId==0)
1827     {
1828       for(int i=0;i<nbOfCells;i++)
1829         {
1830           if(!isFetched[i])
1831             {
1832               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1833               std::vector<int> v,v2;
1834               if(connOfNode!=connPtr+connIPtr[i+1])
1835                 {
1836                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1837                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1838                   connOfNode++;
1839                 }
1840               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1841                 if(*connOfNode>=0)
1842                   {
1843                     v=v2;
1844                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1845                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1846                     v2.resize(std::distance(v2.begin(),it));
1847                   }
1848               if(v2.size()>1)
1849                 {
1850                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1851                     {
1852                       int pos=commonCellsI->back();
1853                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1854                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1855                         isFetched[*it]=true;
1856                     }
1857                 }
1858             }
1859         }
1860     }
1861   else
1862     {
1863       for(int i=startCellId;i<nbOfCells;i++)
1864         {
1865           if(!isFetched[i])
1866             {
1867               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1868               std::vector<int> v,v2;
1869               if(connOfNode!=connPtr+connIPtr[i+1])
1870                 {
1871                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1872                   connOfNode++;
1873                 }
1874               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1875                 if(*connOfNode>=0)
1876                   {
1877                     v=v2;
1878                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1879                     v2.resize(std::distance(v2.begin(),it));
1880                   }
1881               if(v2.size()>1)
1882                 {
1883                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1884                     {
1885                       int pos=commonCellsI->back();
1886                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1887                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1888                         isFetched[*it]=true;
1889                     }
1890                 }
1891             }
1892         }
1893     }
1894   commonCellsArr=commonCells.retn();
1895   commonCellsIArr=commonCellsI.retn();
1896 }
1897
1898 /*!
1899  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1900  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1901  * than \a other->getNumberOfCells() in the returned array means that there is no
1902  * corresponding cell in \a this mesh.
1903  * It is expected that \a this and \a other meshes share the same node coordinates
1904  * array, if it is not so an exception is thrown. 
1905  *  \param [in] other - the mesh to compare with.
1906  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1907  *         valid values [0,1,2], see zipConnectivityTraducer().
1908  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1909  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1910  *         values. The caller is to delete this array using
1911  *         decrRef() as it is no more needed.
1912  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1913  *         mesh.
1914  *
1915  *  \if ENABLE_EXAMPLES
1916  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1917  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1918  *  \endif
1919  *  \sa checkDeepEquivalOnSameNodesWith()
1920  *  \sa checkGeoEquivalWith()
1921  */
1922 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1923 {
1924   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1925   int nbOfCells=getNumberOfCells();
1926   static const int possibleCompType[]={0,1,2};
1927   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1928     {
1929       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1930       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1931       oss << " !";
1932       throw INTERP_KERNEL::Exception(oss.str().c_str());
1933     }
1934   MCAuto<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1935   arr=o2n->subArray(nbOfCells);
1936   arr->setName(other->getName());
1937   int tmp;
1938   if(other->getNumberOfCells()==0)
1939     return true;
1940   return arr->getMaxValue(tmp)<nbOfCells;
1941 }
1942
1943 /*!
1944  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1945  * This method tries to determine if \b other is fully included in \b this.
1946  * The main difference is that this method is not expected to throw exception.
1947  * This method has two outputs :
1948  *
1949  * \param other other mesh
1950  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1951  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1952  */
1953 bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1954 {
1955   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1956   DataArrayInt *commonCells=0,*commonCellsI=0;
1957   int thisNbCells=getNumberOfCells();
1958   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1959   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1960   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1961   int otherNbCells=other->getNumberOfCells();
1962   MCAuto<DataArrayInt> arr2=DataArrayInt::New();
1963   arr2->alloc(otherNbCells,1);
1964   arr2->fillWithZero();
1965   int *arr2Ptr=arr2->getPointer();
1966   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1967   for(int i=0;i<nbOfCommon;i++)
1968     {
1969       int start=commonCellsPtr[commonCellsIPtr[i]];
1970       if(start<thisNbCells)
1971         {
1972           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1973             {
1974               int sig=commonCellsPtr[j]>0?1:-1;
1975               int val=std::abs(commonCellsPtr[j])-1;
1976               if(val>=thisNbCells)
1977                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1978             }
1979         }
1980     }
1981   arr2->setName(other->getName());
1982   if(arr2->presenceOfValue(0))
1983     return false;
1984   arr=arr2.retn();
1985   return true;
1986 }
1987
1988 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1989 {
1990   if(!other)
1991     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1992   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1993   if(!otherC)
1994     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1995   std::vector<const MEDCouplingUMesh *> ms(2);
1996   ms[0]=this;
1997   ms[1]=otherC;
1998   return MergeUMeshesOnSameCoords(ms);
1999 }
2000
2001 /*!
2002  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2003  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2004  * cellIds is not given explicitely but by a range python like.
2005  * 
2006  * \param start
2007  * \param end
2008  * \param step
2009  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see MEDCoupling::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
2010  * \return a newly allocated
2011  * 
2012  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2013  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2014  */
2015 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, int step, bool keepCoords) const
2016 {
2017   if(getMeshDimension()!=-1)
2018     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords));
2019   else
2020     {
2021       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh ");
2022       if(newNbOfCells!=1)
2023         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2024       if(start!=0)
2025         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2026       incrRef();
2027       return const_cast<MEDCouplingUMesh *>(this);
2028     }
2029 }
2030
2031 /*!
2032  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2033  * The result mesh shares or not the node coordinates array with \a this mesh depending
2034  * on \a keepCoords parameter.
2035  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2036  *           to write this mesh to the MED file, its cells must be sorted using
2037  *           sortCellsInMEDFileFrmt().
2038  *  \param [in] begin - an array of cell ids to include to the new mesh.
2039  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2040  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2041  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2042  *         by calling zipCoords().
2043  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2044  *         to delete this mesh using decrRef() as it is no more needed. 
2045  *  \throw If the coordinates array is not set.
2046  *  \throw If the nodal connectivity of cells is not defined.
2047  *  \throw If any cell id in the array \a begin is not valid.
2048  *
2049  *  \if ENABLE_EXAMPLES
2050  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2051  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2052  *  \endif
2053  */
2054 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2055 {
2056   if(getMeshDimension()!=-1)
2057     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
2058   else
2059     {
2060       if(end-begin!=1)
2061         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2062       if(begin[0]!=0)
2063         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2064       incrRef();
2065       return const_cast<MEDCouplingUMesh *>(this);
2066     }
2067 }
2068
2069 /*!
2070  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2071  *
2072  * 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.
2073  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2074  * The number of cells of \b this will remain the same with this method.
2075  *
2076  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2077  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2078  * \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 ).
2079  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2080  */
2081 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2082 {
2083   checkConnectivityFullyDefined();
2084   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2085   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2086     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2087   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2088     {
2089       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2090       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2091       throw INTERP_KERNEL::Exception(oss.str().c_str());
2092     }
2093   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2094   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2095     {
2096       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2097       throw INTERP_KERNEL::Exception(oss.str().c_str());
2098     }
2099   int nbOfCells=getNumberOfCells();
2100   bool easyAssign=true;
2101   const int *connI=_nodal_connec_index->getConstPointer();
2102   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2103   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2104     {
2105       if(*it>=0 && *it<nbOfCells)
2106         {
2107           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2108         }
2109       else
2110         {
2111           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2112           throw INTERP_KERNEL::Exception(oss.str().c_str());
2113         }
2114     }
2115   if(easyAssign)
2116     {
2117       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2118       computeTypes();
2119     }
2120   else
2121     {
2122       DataArrayInt *arrOut=0,*arrIOut=0;
2123       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2124                                                arrOut,arrIOut);
2125       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2126       setConnectivity(arrOut,arrIOut,true);
2127     }
2128 }
2129
2130 void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2131 {
2132   checkConnectivityFullyDefined();
2133   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2134   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2135     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelfSlice : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2136   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2137     {
2138       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2139       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2140       throw INTERP_KERNEL::Exception(oss.str().c_str());
2141     }
2142   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : ");
2143   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2144     {
2145       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2146       throw INTERP_KERNEL::Exception(oss.str().c_str());
2147     }
2148   int nbOfCells=getNumberOfCells();
2149   bool easyAssign=true;
2150   const int *connI=_nodal_connec_index->getConstPointer();
2151   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2152   int it=start;
2153   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2154     {
2155       if(it>=0 && it<nbOfCells)
2156         {
2157           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2158         }
2159       else
2160         {
2161           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2162           throw INTERP_KERNEL::Exception(oss.str().c_str());
2163         }
2164     }
2165   if(easyAssign)
2166     {
2167       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2168       computeTypes();
2169     }
2170   else
2171     {
2172       DataArrayInt *arrOut=0,*arrIOut=0;
2173       MEDCouplingUMesh::SetPartOfIndexedArraysSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2174                                                 arrOut,arrIOut);
2175       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2176       setConnectivity(arrOut,arrIOut,true);
2177     }
2178 }                      
2179
2180 /*!
2181  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2182  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2183  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2184  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2185  *
2186  * \param [in] begin input start of array of node ids.
2187  * \param [in] end input end of array of node ids.
2188  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2189  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2190  */
2191 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2192 {
2193   MCAuto<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2194   checkConnectivityFullyDefined();
2195   int tmp=-1;
2196   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2197   std::vector<bool> fastFinder(sz,false);
2198   for(const int *work=begin;work!=end;work++)
2199     if(*work>=0 && *work<sz)
2200       fastFinder[*work]=true;
2201   int nbOfCells=getNumberOfCells();
2202   const int *conn=getNodalConnectivity()->getConstPointer();
2203   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2204   for(int i=0;i<nbOfCells;i++)
2205     {
2206       int ref=0,nbOfHit=0;
2207       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2208         if(*work2>=0)
2209           {
2210             ref++;
2211             if(fastFinder[*work2])
2212               nbOfHit++;
2213           }
2214       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2215         cellIdsKept->pushBackSilent(i);
2216     }
2217   cellIdsKeptArr=cellIdsKept.retn();
2218 }
2219
2220 /*!
2221  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2222  * this->getMeshDimension(), that bound some cells of \a this mesh.
2223  * The cells of lower dimension to include to the result mesh are selected basing on
2224  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2225  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2226  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2227  * created mesh shares the node coordinates array with \a this mesh. 
2228  *  \param [in] begin - the array of node ids.
2229  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2230  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2231  *         array \a begin are added, else cells whose any node is in the
2232  *         array \a begin are added.
2233  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2234  *         to delete this mesh using decrRef() as it is no more needed. 
2235  *  \throw If the coordinates array is not set.
2236  *  \throw If the nodal connectivity of cells is not defined.
2237  *  \throw If any node id in \a begin is not valid.
2238  *
2239  *  \if ENABLE_EXAMPLES
2240  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2241  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2242  *  \endif
2243  */
2244 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2245 {
2246   MCAuto<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2247   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2248   MCAuto<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2249   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2250   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2251 }
2252
2253 /*!
2254  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2255  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2256  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2257  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2258  *         by calling zipCoords().
2259  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2260  *         to delete this mesh using decrRef() as it is no more needed. 
2261  *  \throw If the coordinates array is not set.
2262  *  \throw If the nodal connectivity of cells is not defined.
2263  *
2264  *  \if ENABLE_EXAMPLES
2265  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2266  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2267  *  \endif
2268  */
2269 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2270 {
2271   DataArrayInt *desc=DataArrayInt::New();
2272   DataArrayInt *descIndx=DataArrayInt::New();
2273   DataArrayInt *revDesc=DataArrayInt::New();
2274   DataArrayInt *revDescIndx=DataArrayInt::New();
2275   //
2276   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2277   revDesc->decrRef();
2278   desc->decrRef();
2279   descIndx->decrRef();
2280   int nbOfCells=meshDM1->getNumberOfCells();
2281   const int *revDescIndxC=revDescIndx->getConstPointer();
2282   std::vector<int> boundaryCells;
2283   for(int i=0;i<nbOfCells;i++)
2284     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2285       boundaryCells.push_back(i);
2286   revDescIndx->decrRef();
2287   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2288   return ret;
2289 }
2290
2291 /*!
2292  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2293  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2294  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2295  */
2296 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2297 {
2298   checkFullyDefined();
2299   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2300   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2301   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2302   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2303   //
2304   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2305   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2306   //
2307   MCAuto<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2308   MCAuto<DataArrayInt> faceIds=tmp->findIdsEqual(1); tmp=(DataArrayInt*)0;
2309   const int *revDescPtr=revDesc->getConstPointer();
2310   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2311   int nbOfCells=getNumberOfCells();
2312   std::vector<bool> ret1(nbOfCells,false);
2313   int sz=0;
2314   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2315     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2316       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2317   //
2318   DataArrayInt *ret2=DataArrayInt::New();
2319   ret2->alloc(sz,1);
2320   int *ret2Ptr=ret2->getPointer();
2321   sz=0;
2322   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2323     if(*it)
2324       *ret2Ptr++=sz;
2325   ret2->setName("BoundaryCells");
2326   return ret2;
2327 }
2328
2329 /*!
2330  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2331  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2332  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2333  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2334  *
2335  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2336  * This method also returns the cells ids set s1 which contains the cell ids in \b this for which one of the dim-1 constituent
2337  * equals a cell in \b otherDimM1OnSameCoords.
2338  *
2339  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2340  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2341  *
2342  * \param [in] otherDimM1OnSameCoords
2343  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2344  * \param [out] cellIdsRk1 a newly allocated array containing the cell ids of s1 \b indexed into the \b cellIdsRk0 subset. To get the absolute ids of s1, simply invoke
2345  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2346  */
2347 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2348 {
2349   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2350     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2351   checkConnectivityFullyDefined();
2352   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2353   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2354     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2355   MCAuto<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2356   MCAuto<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2357   MCAuto<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2358   MCAuto<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2359   MCAuto<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2360   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2361   DataArrayInt *idsOtherInConsti=0;
2362   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2363   MCAuto<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2364   if(!b)
2365     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2366   std::set<int> s1;
2367   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2368     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2369   MCAuto<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2370   s1arr_renum1->sort();
2371   cellIdsRk0=s0arr.retn();
2372   //cellIdsRk1=s_renum1.retn();
2373   cellIdsRk1=s1arr_renum1.retn();
2374 }
2375
2376 /*!
2377  * 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
2378  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2379  * 
2380  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2381  */
2382 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2383 {
2384   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2385   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2386   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2387   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2388   //
2389   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2390   revDesc=0; desc=0; descIndx=0;
2391   MCAuto<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2392   MCAuto<DataArrayInt> part=revDescIndx2->findIdsEqual(1);
2393   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2394 }
2395
2396 /*!
2397  * Finds nodes lying on the boundary of \a this mesh.
2398  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2399  *          nodes. The caller is to delete this array using decrRef() as it is no
2400  *          more needed.
2401  *  \throw If the coordinates array is not set.
2402  *  \throw If the nodal connectivity of cells is node defined.
2403  *
2404  *  \if ENABLE_EXAMPLES
2405  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2406  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2407  *  \endif
2408  */
2409 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2410 {
2411   MCAuto<MEDCouplingUMesh> skin=computeSkin();
2412   return skin->computeFetchedNodeIds();
2413 }
2414
2415 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2416 {
2417   incrRef();
2418   return const_cast<MEDCouplingUMesh *>(this);
2419 }
2420
2421 /*!
2422  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2423  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2424  * 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.
2425  * 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.
2426  * 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.
2427  *
2428  * \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
2429  *             parameter is altered during the call.
2430  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2431  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2432  * \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.
2433  *
2434  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2435  */
2436 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2437                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2438 {
2439   typedef MCAuto<DataArrayInt> DAInt;
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   DAInt cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2450   DAInt s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2451   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2452   MCAuto<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2453   DAInt s1=m0Part->computeFetchedNodeIds();
2454   DAInt s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2455   DAInt s3=s2->buildSubstraction(s1);
2456   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2457   //
2458   MCAuto<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2459   int nCells2 = m0Part2->getNumberOfCells();
2460   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2461   MCAuto<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2462   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2463   DataArrayInt *tmp00=0,*tmp11=0;
2464   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2465   DAInt neighInit00(tmp00);
2466   DAInt neighIInit00(tmp11);
2467   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2468   DataArrayInt *idsTmp=0;
2469   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2470   DAInt ids(idsTmp);
2471   if(!b)
2472     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2473   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2474   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2475   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2476   DataArrayInt *tmp0=0,*tmp1=0;
2477   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2478   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2479   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2480   DAInt neigh00(tmp0);
2481   DAInt neighI00(tmp1);
2482
2483   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2484   int seed = 0, nIter = 0;
2485   int nIterMax = nCells2+1; // Safety net for the loop
2486   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2487   hitCells->fillWithValue(-1);
2488   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2489   cellsToModifyConn0_torenum->alloc(0,1);
2490   while (nIter < nIterMax)
2491     {
2492       DAInt t = hitCells->findIdsEqual(-1);
2493       if (!t->getNumberOfTuples())
2494         break;
2495       // Connex zone without the crack (to compute the next seed really)
2496       int dnu;
2497       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2498       int cnt = 0;
2499       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2500         hitCells->setIJ(*ptr,0,1);
2501       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2502       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2503       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2504       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2505       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2506       DAInt nonHitCells = hitCells->findIdsEqual(-1);
2507       DAInt intersec = nonHitCells->buildIntersection(comple);
2508       if (intersec->getNumberOfTuples())
2509         { seed = intersec->getIJ(0,0); }
2510       else
2511         { break; }
2512       nIter++;
2513     }
2514   if (nIter >= nIterMax)
2515     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2516
2517   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2518   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2519   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2520   //
2521   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2522   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2523   nodeIdsToDuplicate=s3.retn();
2524 }
2525
2526 /*!
2527  * This method operates a modification of the connectivity and coords in \b this.
2528  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2529  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2530  * 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
2531  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2532  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2533  * 
2534  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2535  * 
2536  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2537  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2538  */
2539 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2540 {
2541   int nbOfNodes=getNumberOfNodes();
2542   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2543   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2544 }
2545
2546 /*!
2547  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2548  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2549  *
2550  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2551  *
2552  * \sa renumberNodesInConn
2553  */
2554 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2555 {
2556   checkConnectivityFullyDefined();
2557   int *conn(getNodalConnectivity()->getPointer());
2558   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2559   int nbOfCells(getNumberOfCells());
2560   for(int i=0;i<nbOfCells;i++)
2561     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2562       {
2563         int& node=conn[iconn];
2564         if(node>=0)//avoid polyhedron separator
2565           {
2566             node+=offset;
2567           }
2568       }
2569   _nodal_connec->declareAsNew();
2570   updateTime();
2571 }
2572
2573 /*!
2574  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2575  *  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
2576  *  of a big mesh.
2577  */
2578 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2579 {
2580   checkConnectivityFullyDefined();
2581   int *conn(getNodalConnectivity()->getPointer());
2582   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2583   int nbOfCells(getNumberOfCells());
2584   for(int i=0;i<nbOfCells;i++)
2585     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2586       {
2587         int& node=conn[iconn];
2588         if(node>=0)//avoid polyhedron separator
2589           {
2590             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2591             if(it!=newNodeNumbersO2N.end())
2592               {
2593                 node=(*it).second;
2594               }
2595             else
2596               {
2597                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2598                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2599               }
2600           }
2601       }
2602   _nodal_connec->declareAsNew();
2603   updateTime();
2604 }
2605
2606 /*!
2607  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2608  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2609  * This method is a generalization of shiftNodeNumbersInConn().
2610  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2611  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2612  *         this->getNumberOfNodes(), in "Old to New" mode. 
2613  *         See \ref numbering for more info on renumbering modes.
2614  *  \throw If the nodal connectivity of cells is not defined.
2615  *
2616  *  \if ENABLE_EXAMPLES
2617  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2618  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2619  *  \endif
2620  */
2621 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2622 {
2623   checkConnectivityFullyDefined();
2624   int *conn=getNodalConnectivity()->getPointer();
2625   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2626   int nbOfCells(getNumberOfCells());
2627   for(int i=0;i<nbOfCells;i++)
2628     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2629       {
2630         int& node=conn[iconn];
2631         if(node>=0)//avoid polyhedron separator
2632           {
2633             node=newNodeNumbersO2N[node];
2634           }
2635       }
2636   _nodal_connec->declareAsNew();
2637   updateTime();
2638 }
2639
2640 /*!
2641  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2642  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2643  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2644  * 
2645  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2646  */
2647 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2648 {
2649   checkConnectivityFullyDefined();
2650   int *conn=getNodalConnectivity()->getPointer();
2651   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2652   int nbOfCells=getNumberOfCells();
2653   for(int i=0;i<nbOfCells;i++)
2654     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2655       {
2656         int& node=conn[iconn];
2657         if(node>=0)//avoid polyhedron separator
2658           {
2659             node+=delta;
2660           }
2661       }
2662   _nodal_connec->declareAsNew();
2663   updateTime();
2664 }
2665
2666 /*!
2667  * This method operates a modification of the connectivity in \b this.
2668  * 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.
2669  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2670  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2671  * 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
2672  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2673  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2674  * 
2675  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2676  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2677  * 
2678  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2679  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2680  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2681  */
2682 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2683 {
2684   checkConnectivityFullyDefined();
2685   std::map<int,int> m;
2686   int val=offset;
2687   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2688     m[*work]=val;
2689   int *conn=getNodalConnectivity()->getPointer();
2690   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2691   int nbOfCells=getNumberOfCells();
2692   for(int i=0;i<nbOfCells;i++)
2693     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2694       {
2695         int& node=conn[iconn];
2696         if(node>=0)//avoid polyhedron separator
2697           {
2698             std::map<int,int>::iterator it=m.find(node);
2699             if(it!=m.end())
2700               node=(*it).second;
2701           }
2702       }
2703   updateTime();
2704 }
2705
2706 /*!
2707  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2708  *
2709  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2710  * After the call of this method the number of cells remains the same as before.
2711  *
2712  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2713  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2714  * be strictly in [0;this->getNumberOfCells()).
2715  *
2716  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2717  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2718  * should be contained in[0;this->getNumberOfCells()).
2719  * 
2720  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2721  * \param check
2722  */
2723 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2724 {
2725   checkConnectivityFullyDefined();
2726   int nbCells=getNumberOfCells();
2727   const int *array=old2NewBg;
2728   if(check)
2729     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2730   //
2731   const int *conn=_nodal_connec->getConstPointer();
2732   const int *connI=_nodal_connec_index->getConstPointer();
2733   MCAuto<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2734   MCAuto<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2735   const int *n2oPtr=n2o->begin();
2736   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
2737   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2738   newConn->copyStringInfoFrom(*_nodal_connec);
2739   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
2740   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2741   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2742   //
2743   int *newC=newConn->getPointer();
2744   int *newCI=newConnI->getPointer();
2745   int loc=0;
2746   newCI[0]=loc;
2747   for(int i=0;i<nbCells;i++)
2748     {
2749       int pos=n2oPtr[i];
2750       int nbOfElts=connI[pos+1]-connI[pos];
2751       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2752       loc+=nbOfElts;
2753       newCI[i+1]=loc;
2754     }
2755   //
2756   setConnectivity(newConn,newConnI);
2757   if(check)
2758     free(const_cast<int *>(array));
2759 }
2760
2761 /*!
2762  * Finds cells whose bounding boxes intersect a given bounding box.
2763  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2764  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2765  *         zMax (if in 3D). 
2766  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2767  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2768  *         extent of the bounding box of cell to produce an addition to this bounding box.
2769  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2770  *         cells. The caller is to delete this array using decrRef() as it is no more
2771  *         needed. 
2772  *  \throw If the coordinates array is not set.
2773  *  \throw If the nodal connectivity of cells is not defined.
2774  *
2775  *  \if ENABLE_EXAMPLES
2776  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2777  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2778  *  \endif
2779  */
2780 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2781 {
2782   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2783   if(getMeshDimension()==-1)
2784     {
2785       elems->pushBackSilent(0);
2786       return elems.retn();
2787     }
2788   int dim=getSpaceDimension();
2789   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2790   const int* conn      = getNodalConnectivity()->getConstPointer();
2791   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2792   const double* coords = getCoords()->getConstPointer();
2793   int nbOfCells=getNumberOfCells();
2794   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2795     {
2796       for (int i=0; i<dim; i++)
2797         {
2798           elem_bb[i*2]=std::numeric_limits<double>::max();
2799           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2800         }
2801
2802       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2803         {
2804           int node= conn[inode];
2805           if(node>=0)//avoid polyhedron separator
2806             {
2807               for (int idim=0; idim<dim; idim++)
2808                 {
2809                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2810                     {
2811                       elem_bb[idim*2] = coords[node*dim+idim] ;
2812                     }
2813                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2814                     {
2815                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2816                     }
2817                 }
2818             }
2819         }
2820       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2821         elems->pushBackSilent(ielem);
2822     }
2823   return elems.retn();
2824 }
2825
2826 /*!
2827  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2828  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2829  * added in 'elems' parameter.
2830  */
2831 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2832 {
2833   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2834   if(getMeshDimension()==-1)
2835     {
2836       elems->pushBackSilent(0);
2837       return elems.retn();
2838     }
2839   int dim=getSpaceDimension();
2840   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2841   const int* conn      = getNodalConnectivity()->getConstPointer();
2842   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2843   const double* coords = getCoords()->getConstPointer();
2844   int nbOfCells=getNumberOfCells();
2845   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2846     {
2847       for (int i=0; i<dim; i++)
2848         {
2849           elem_bb[i*2]=std::numeric_limits<double>::max();
2850           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2851         }
2852
2853       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2854         {
2855           int node= conn[inode];
2856           if(node>=0)//avoid polyhedron separator
2857             {
2858               for (int idim=0; idim<dim; idim++)
2859                 {
2860                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2861                     {
2862                       elem_bb[idim*2] = coords[node*dim+idim] ;
2863                     }
2864                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2865                     {
2866                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2867                     }
2868                 }
2869             }
2870         }
2871       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2872         elems->pushBackSilent(ielem);
2873     }
2874   return elems.retn();
2875 }
2876
2877 /*!
2878  * Returns a type of a cell by its id.
2879  *  \param [in] cellId - the id of the cell of interest.
2880  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2881  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2882  */
2883 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2884 {
2885   const int *ptI=_nodal_connec_index->getConstPointer();
2886   const int *pt=_nodal_connec->getConstPointer();
2887   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2888     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2889   else
2890     {
2891       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2892       throw INTERP_KERNEL::Exception(oss.str().c_str());
2893     }
2894 }
2895
2896 /*!
2897  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2898  * This method does not throw exception if geometric type \a type is not in \a this.
2899  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2900  * The coordinates array is not considered here.
2901  *
2902  * \param [in] type the geometric type
2903  * \return cell ids in this having geometric type \a type.
2904  */
2905 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2906 {
2907
2908   MCAuto<DataArrayInt> ret=DataArrayInt::New();
2909   ret->alloc(0,1);
2910   checkConnectivityFullyDefined();
2911   int nbCells=getNumberOfCells();
2912   int mdim=getMeshDimension();
2913   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2914   if(mdim!=(int)cm.getDimension())
2915     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2916   const int *ptI=_nodal_connec_index->getConstPointer();
2917   const int *pt=_nodal_connec->getConstPointer();
2918   for(int i=0;i<nbCells;i++)
2919     {
2920       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2921         ret->pushBackSilent(i);
2922     }
2923   return ret.retn();
2924 }
2925
2926 /*!
2927  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2928  */
2929 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2930 {
2931   const int *ptI=_nodal_connec_index->getConstPointer();
2932   const int *pt=_nodal_connec->getConstPointer();
2933   int nbOfCells=getNumberOfCells();
2934   int ret=0;
2935   for(int i=0;i<nbOfCells;i++)
2936     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2937       ret++;
2938   return ret;
2939 }
2940
2941 /*!
2942  * Returns the nodal connectivity of a given cell.
2943  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2944  * all returned node ids can be used in getCoordinatesOfNode().
2945  *  \param [in] cellId - an id of the cell of interest.
2946  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2947  *         cleared before the appending.
2948  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2949  */
2950 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2951 {
2952   const int *ptI=_nodal_connec_index->getConstPointer();
2953   const int *pt=_nodal_connec->getConstPointer();
2954   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2955     if(*w>=0)
2956       conn.push_back(*w);
2957 }
2958
2959 std::string MEDCouplingUMesh::simpleRepr() const
2960 {
2961   static const char msg0[]="No coordinates specified !";
2962   std::ostringstream ret;
2963   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2964   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2965   int tmpp1,tmpp2;
2966   double tt=getTime(tmpp1,tmpp2);
2967   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2968   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2969   if(_mesh_dim>=-1)
2970     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2971   else
2972     { ret << " Mesh dimension has not been set or is invalid !"; }
2973   if(_coords!=0)
2974     {
2975       const int spaceDim=getSpaceDimension();
2976       ret << spaceDim << "\nInfo attached on space dimension : ";
2977       for(int i=0;i<spaceDim;i++)
2978         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2979       ret << "\n";
2980     }
2981   else
2982     ret << msg0 << "\n";
2983   ret << "Number of nodes : ";
2984   if(_coords!=0)
2985     ret << getNumberOfNodes() << "\n";
2986   else
2987     ret << msg0 << "\n";
2988   ret << "Number of cells : ";
2989   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2990     ret << getNumberOfCells() << "\n";
2991   else
2992     ret << "No connectivity specified !" << "\n";
2993   ret << "Cell types present : ";
2994   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2995     {
2996       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2997       ret << cm.getRepr() << " ";
2998     }
2999   ret << "\n";
3000   return ret.str();
3001 }
3002
3003 std::string MEDCouplingUMesh::advancedRepr() const
3004 {
3005   std::ostringstream ret;
3006   ret << simpleRepr();
3007   ret << "\nCoordinates array : \n___________________\n\n";
3008   if(_coords)
3009     _coords->reprWithoutNameStream(ret);
3010   else
3011     ret << "No array set !\n";
3012   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3013   reprConnectivityOfThisLL(ret);
3014   return ret.str();
3015 }
3016
3017 /*!
3018  * This method returns a C++ code that is a dump of \a this.
3019  * This method will throw if this is not fully defined.
3020  */
3021 std::string MEDCouplingUMesh::cppRepr() const
3022 {
3023   static const char coordsName[]="coords";
3024   static const char connName[]="conn";
3025   static const char connIName[]="connI";
3026   checkFullyDefined();
3027   std::ostringstream ret; ret << "// coordinates" << std::endl;
3028   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3029   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3030   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3031   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3032   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3033   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3034   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3035   return ret.str();
3036 }
3037
3038 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3039 {
3040   std::ostringstream ret;
3041   reprConnectivityOfThisLL(ret);
3042   return ret.str();
3043 }
3044
3045 /*!
3046  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3047  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3048  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3049  * some algos).
3050  * 
3051  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3052  * 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
3053  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3054  */
3055 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3056 {
3057   int mdim=getMeshDimension();
3058   if(mdim<0)
3059     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3060   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3061   MCAuto<DataArrayInt> tmp1,tmp2;
3062   bool needToCpyCT=true;
3063   if(!_nodal_connec)
3064     {
3065       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3066       needToCpyCT=false;
3067     }
3068   else
3069     {
3070       tmp1=_nodal_connec;
3071       tmp1->incrRef();
3072     }
3073   if(!_nodal_connec_index)
3074     {
3075       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3076       needToCpyCT=false;
3077     }
3078   else
3079     {
3080       tmp2=_nodal_connec_index;
3081       tmp2->incrRef();
3082     }
3083   ret->setConnectivity(tmp1,tmp2,false);
3084   if(needToCpyCT)
3085     ret->_types=_types;
3086   if(!_coords)
3087     {
3088       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3089       ret->setCoords(coords);
3090     }
3091   else
3092     ret->setCoords(_coords);
3093   return ret.retn();
3094 }
3095
3096 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3097 {
3098   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3099     {
3100       int nbOfCells=getNumberOfCells();
3101       const int *c=_nodal_connec->getConstPointer();
3102       const int *ci=_nodal_connec_index->getConstPointer();
3103       for(int i=0;i<nbOfCells;i++)
3104         {
3105           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3106           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3107           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3108           stream << "\n";
3109         }
3110     }
3111   else
3112     stream << "Connectivity not defined !\n";
3113 }
3114
3115 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3116 {
3117   const int *ptI=_nodal_connec_index->getConstPointer();
3118   const int *pt=_nodal_connec->getConstPointer();
3119   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3120     return ptI[cellId+1]-ptI[cellId]-1;
3121   else
3122     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3123 }
3124
3125 /*!
3126  * Returns types of cells of the specified part of \a this mesh.
3127  * This method avoids computing sub-mesh explicitely to get its types.
3128  *  \param [in] begin - an array of cell ids of interest.
3129  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3130  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3131  *         describing the cell types. 
3132  *  \throw If the coordinates array is not set.
3133  *  \throw If the nodal connectivity of cells is not defined.
3134  *  \sa getAllGeoTypes()
3135  */
3136 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3137 {
3138   checkFullyDefined();
3139   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3140   const int *conn=_nodal_connec->getConstPointer();
3141   const int *connIndex=_nodal_connec_index->getConstPointer();
3142   for(const int *w=begin;w!=end;w++)
3143     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3144   return ret;
3145 }
3146
3147 /*!
3148  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3149  * Optionally updates
3150  * a set of types of cells constituting \a this mesh. 
3151  * This method is for advanced users having prepared their connectivity before. For
3152  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3153  *  \param [in] conn - the nodal connectivity array. 
3154  *  \param [in] connIndex - the nodal connectivity index array.
3155  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3156  *         mesh is updated.
3157  */
3158 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3159 {
3160   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3161   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3162   if(isComputingTypes)
3163     computeTypes();
3164   declareAsNew();
3165 }
3166
3167 /*!
3168  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3169  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3170  */
3171 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3172     _nodal_connec(0),_nodal_connec_index(0),
3173     _types(other._types)
3174 {
3175   if(other._nodal_connec)
3176     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCopy);
3177   if(other._nodal_connec_index)
3178     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCopy);
3179 }
3180
3181 MEDCouplingUMesh::~MEDCouplingUMesh()
3182 {
3183   if(_nodal_connec)
3184     _nodal_connec->decrRef();
3185   if(_nodal_connec_index)
3186     _nodal_connec_index->decrRef();
3187 }
3188
3189 /*!
3190  * Recomputes a set of cell types of \a this mesh. For more info see
3191  * \ref MEDCouplingUMeshNodalConnectivity.
3192  */
3193 void MEDCouplingUMesh::computeTypes()
3194 {
3195   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3196 }
3197
3198 /*!
3199  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3200  */
3201 void MEDCouplingUMesh::checkFullyDefined() const
3202 {
3203   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3204     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3205 }
3206
3207 /*!
3208  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3209  */
3210 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3211 {
3212   if(!_nodal_connec_index || !_nodal_connec)
3213     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3214 }
3215
3216 /*!
3217  * Returns a number of cells constituting \a this mesh. 
3218  *  \return int - the number of cells in \a this mesh.
3219  *  \throw If the nodal connectivity of cells is not defined.
3220  */
3221 int MEDCouplingUMesh::getNumberOfCells() const
3222
3223   if(_nodal_connec_index)
3224     return _nodal_connec_index->getNumberOfTuples()-1;
3225   else
3226     if(_mesh_dim==-1)
3227       return 1;
3228     else
3229       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3230 }
3231
3232 /*!
3233  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3234  * mesh. For more info see \ref meshes.
3235  *  \return int - the dimension of \a this mesh.
3236  *  \throw If the mesh dimension is not defined using setMeshDimension().
3237  */
3238 int MEDCouplingUMesh::getMeshDimension() const
3239 {
3240   if(_mesh_dim<-1)
3241     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3242   return _mesh_dim;
3243 }
3244
3245 /*!
3246  * Returns a length of the nodal connectivity array.
3247  * This method is for test reason. Normally the integer returned is not useable by
3248  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3249  *  \return int - the length of the nodal connectivity array.
3250  */
3251 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3252 {
3253   return _nodal_connec->getNbOfElems();
3254 }
3255
3256 /*!
3257  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3258  */
3259 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3260 {
3261   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3262   tinyInfo.push_back(getMeshDimension());
3263   tinyInfo.push_back(getNumberOfCells());
3264   if(_nodal_connec)
3265     tinyInfo.push_back(getNodalConnectivityArrayLen());
3266   else
3267     tinyInfo.push_back(-1);
3268 }
3269
3270 /*!
3271  * First step of unserialization process.
3272  */
3273 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3274 {
3275   return tinyInfo[6]<=0;
3276 }
3277
3278 /*!
3279  * Second step of serialization process.
3280  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3281  * \param a1
3282  * \param a2
3283  * \param littleStrings
3284  */
3285 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3286 {
3287   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3288   if(tinyInfo[5]!=-1)
3289     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3290 }
3291
3292 /*!
3293  * Third and final step of serialization process.
3294  */
3295 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3296 {
3297   MEDCouplingPointSet::serialize(a1,a2);
3298   if(getMeshDimension()>-1)
3299     {
3300       a1=DataArrayInt::New();
3301       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3302       int *ptA1=a1->getPointer();
3303       const int *conn=getNodalConnectivity()->getConstPointer();
3304       const int *index=getNodalConnectivityIndex()->getConstPointer();
3305       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3306       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3307     }
3308   else
3309     a1=0;
3310 }
3311
3312 /*!
3313  * Second and final unserialization process.
3314  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3315  */
3316 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3317 {
3318   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3319   setMeshDimension(tinyInfo[5]);
3320   if(tinyInfo[7]!=-1)
3321     {
3322       // Connectivity
3323       const int *recvBuffer=a1->getConstPointer();
3324       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3325       myConnecIndex->alloc(tinyInfo[6]+1,1);
3326       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3327       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3328       myConnec->alloc(tinyInfo[7],1);
3329       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3330       setConnectivity(myConnec, myConnecIndex);
3331     }
3332 }
3333
3334 /*!
3335  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelfSlice.
3336  * CellIds are given using range specified by a start an end and step.
3337  */
3338 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice(int start, int end, int step) const
3339 {
3340   checkFullyDefined();
3341   int ncell=getNumberOfCells();
3342   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3343   ret->_mesh_dim=_mesh_dim;
3344   ret->setCoords(_coords);
3345   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : ");
3346   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3347   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3348   int work=start;
3349   const int *conn=_nodal_connec->getConstPointer();
3350   const int *connIndex=_nodal_connec_index->getConstPointer();
3351   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3352     {
3353       if(work>=0 && work<ncell)
3354         {
3355           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3356         }
3357       else
3358         {
3359           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3360           throw INTERP_KERNEL::Exception(oss.str().c_str());
3361         }
3362     }
3363   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3364   int *newConnPtr=newConn->getPointer();
3365   std::set<INTERP_KERNEL::NormalizedCellType> types;
3366   work=start;
3367   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3368     {
3369       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3370       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3371     }
3372   ret->setConnectivity(newConn,newConnI,false);
3373   ret->_types=types;
3374   ret->copyTinyInfoFrom(this);
3375   return ret.retn();
3376 }
3377
3378 /*!
3379  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3380  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3381  * The return newly allocated mesh will share the same coordinates as \a this.
3382  */
3383 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3384 {
3385   checkConnectivityFullyDefined();
3386   int ncell=getNumberOfCells();
3387   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3388   ret->_mesh_dim=_mesh_dim;
3389   ret->setCoords(_coords);
3390   std::size_t nbOfElemsRet=std::distance(begin,end);
3391   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3392   connIndexRet[0]=0;
3393   const int *conn=_nodal_connec->getConstPointer();
3394   const int *connIndex=_nodal_connec_index->getConstPointer();
3395   int newNbring=0;
3396   for(const int *work=begin;work!=end;work++,newNbring++)
3397     {
3398       if(*work>=0 && *work<ncell)
3399         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3400       else
3401         {
3402           free(connIndexRet);
3403           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3404           throw INTERP_KERNEL::Exception(oss.str().c_str());
3405         }
3406     }
3407   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3408   int *connRetWork=connRet;
3409   std::set<INTERP_KERNEL::NormalizedCellType> types;
3410   for(const int *work=begin;work!=end;work++)
3411     {
3412       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3413       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3414     }
3415   MCAuto<DataArrayInt> connRetArr=DataArrayInt::New();
3416   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3417   MCAuto<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3418   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3419   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3420   ret->_types=types;
3421   ret->copyTinyInfoFrom(this);
3422   return ret.retn();
3423 }
3424
3425 /*!
3426  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3427  * mesh.<br>
3428  * For 1D cells, the returned field contains lengths.<br>
3429  * For 2D cells, the returned field contains areas.<br>
3430  * For 3D cells, the returned field contains volumes.
3431  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3432  *         orientation, i.e. the volume is always positive.
3433  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3434  *         and one time . The caller is to delete this field using decrRef() as it is no
3435  *         more needed.
3436  */
3437 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3438 {
3439   std::string name="MeasureOfMesh_";
3440   name+=getName();
3441   int nbelem=getNumberOfCells();
3442   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3443   field->setName(name);
3444   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3445   array->alloc(nbelem,1);
3446   double *area_vol=array->getPointer();
3447   field->setArray(array) ; array=0;
3448   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3449   field->synchronizeTimeWithMesh();
3450   if(getMeshDimension()!=-1)
3451     {
3452       int ipt;
3453       INTERP_KERNEL::NormalizedCellType type;
3454       int dim_space=getSpaceDimension();
3455       const double *coords=getCoords()->getConstPointer();
3456       const int *connec=getNodalConnectivity()->getConstPointer();
3457       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3458       for(int iel=0;iel<nbelem;iel++)
3459         {
3460           ipt=connec_index[iel];
3461           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3462           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);
3463         }
3464       if(isAbs)
3465         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3466     }
3467   else
3468     {
3469       area_vol[0]=std::numeric_limits<double>::max();
3470     }
3471   return field.retn();
3472 }
3473
3474 /*!
3475  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3476  * mesh.<br>
3477  * For 1D cells, the returned array contains lengths.<br>
3478  * For 2D cells, the returned array contains areas.<br>
3479  * For 3D cells, the returned array contains volumes.
3480  * This method avoids building explicitly a part of \a this mesh to perform the work.
3481  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3482  *         orientation, i.e. the volume is always positive.
3483  *  \param [in] begin - an array of cell ids of interest.
3484  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3485  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3486  *          delete this array using decrRef() as it is no more needed.
3487  * 
3488  *  \if ENABLE_EXAMPLES
3489  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3490  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3491  *  \endif
3492  *  \sa getMeasureField()
3493  */
3494 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3495 {
3496   std::string name="PartMeasureOfMesh_";
3497   name+=getName();
3498   int nbelem=(int)std::distance(begin,end);
3499   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3500   array->setName(name);
3501   array->alloc(nbelem,1);
3502   double *area_vol=array->getPointer();
3503   if(getMeshDimension()!=-1)
3504     {
3505       int ipt;
3506       INTERP_KERNEL::NormalizedCellType type;
3507       int dim_space=getSpaceDimension();
3508       const double *coords=getCoords()->getConstPointer();
3509       const int *connec=getNodalConnectivity()->getConstPointer();
3510       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3511       for(const int *iel=begin;iel!=end;iel++)
3512         {
3513           ipt=connec_index[*iel];
3514           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3515           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3516         }
3517       if(isAbs)
3518         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3519     }
3520   else
3521     {
3522       area_vol[0]=std::numeric_limits<double>::max();
3523     }
3524   return array.retn();
3525 }
3526
3527 /*!
3528  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3529  * \a this one. The returned field contains the dual cell volume for each corresponding
3530  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3531  *  the dual mesh in P1 sens of \a this.<br>
3532  * For 1D cells, the returned field contains lengths.<br>
3533  * For 2D cells, the returned field contains areas.<br>
3534  * For 3D cells, the returned field contains volumes.
3535  * This method is useful to check "P1*" conservative interpolators.
3536  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3537  *         orientation, i.e. the volume is always positive.
3538  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3539  *          nodes and one time. The caller is to delete this array using decrRef() as
3540  *          it is no more needed.
3541  */
3542 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3543 {
3544   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3545   std::string name="MeasureOnNodeOfMesh_";
3546   name+=getName();
3547   int nbNodes=getNumberOfNodes();
3548   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3549   double cst=1./((double)getMeshDimension()+1.);
3550   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3551   array->alloc(nbNodes,1);
3552   double *valsToFill=array->getPointer();
3553   std::fill(valsToFill,valsToFill+nbNodes,0.);
3554   const double *values=tmp->getArray()->getConstPointer();
3555   MCAuto<DataArrayInt> da=DataArrayInt::New();
3556   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3557   getReverseNodalConnectivity(da,daInd);
3558   const int *daPtr=da->getConstPointer();
3559   const int *daIPtr=daInd->getConstPointer();
3560   for(int i=0;i<nbNodes;i++)
3561     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3562       valsToFill[i]+=cst*values[*cell];
3563   ret->setMesh(this);
3564   ret->setArray(array);
3565   return ret.retn();
3566 }
3567
3568 /*!
3569  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3570  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3571  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3572  * and are normalized.
3573  * <br> \a this can be either 
3574  * - a  2D mesh in 2D or 3D space or 
3575  * - an 1D mesh in 2D space.
3576  * 
3577  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3578  *          cells and one time. The caller is to delete this field using decrRef() as
3579  *          it is no more needed.
3580  *  \throw If the nodal connectivity of cells is not defined.
3581  *  \throw If the coordinates array is not set.
3582  *  \throw If the mesh dimension is not set.
3583  *  \throw If the mesh and space dimension is not as specified above.
3584  */
3585 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3586 {
3587   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3588     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3589   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3590   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3591   int nbOfCells=getNumberOfCells();
3592   int nbComp=getMeshDimension()+1;
3593   array->alloc(nbOfCells,nbComp);
3594   double *vals=array->getPointer();
3595   const int *connI=_nodal_connec_index->getConstPointer();
3596   const int *conn=_nodal_connec->getConstPointer();
3597   const double *coords=_coords->getConstPointer();
3598   if(getMeshDimension()==2)
3599     {
3600       if(getSpaceDimension()==3)
3601         {
3602           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3603           const double *locPtr=loc->getConstPointer();
3604           for(int i=0;i<nbOfCells;i++,vals+=3)
3605             {
3606               int offset=connI[i];
3607               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3608               double n=INTERP_KERNEL::norm<3>(vals);
3609               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3610             }
3611         }
3612       else
3613         {
3614           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3615           const double *isAbsPtr=isAbs->getArray()->begin();
3616           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3617             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3618         }
3619     }
3620   else//meshdimension==1
3621     {
3622       double tmp[2];
3623       for(int i=0;i<nbOfCells;i++)
3624         {
3625           int offset=connI[i];
3626           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3627           double n=INTERP_KERNEL::norm<2>(tmp);
3628           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3629           *vals++=-tmp[1];
3630           *vals++=tmp[0];
3631         }
3632     }
3633   ret->setArray(array);
3634   ret->setMesh(this);
3635   ret->synchronizeTimeWithSupport();
3636   return ret.retn();
3637 }
3638
3639 /*!
3640  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3641  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3642  * and are normalized.
3643  * <br> \a this can be either 
3644  * - a  2D mesh in 2D or 3D space or 
3645  * - an 1D mesh in 2D space.
3646  * 
3647  * This method avoids building explicitly a part of \a this mesh to perform the work.
3648  *  \param [in] begin - an array of cell ids of interest.
3649  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3650  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3651  *          cells and one time. The caller is to delete this field using decrRef() as
3652  *          it is no more needed.
3653  *  \throw If the nodal connectivity of cells is not defined.
3654  *  \throw If the coordinates array is not set.
3655  *  \throw If the mesh dimension is not set.
3656  *  \throw If the mesh and space dimension is not as specified above.
3657  *  \sa buildOrthogonalField()
3658  *
3659  *  \if ENABLE_EXAMPLES
3660  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3661  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3662  *  \endif
3663  */
3664 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3665 {
3666   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3667     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3668   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3669   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3670   std::size_t nbelems=std::distance(begin,end);
3671   int nbComp=getMeshDimension()+1;
3672   array->alloc((int)nbelems,nbComp);
3673   double *vals=array->getPointer();
3674   const int *connI=_nodal_connec_index->getConstPointer();
3675   const int *conn=_nodal_connec->getConstPointer();
3676   const double *coords=_coords->getConstPointer();
3677   if(getMeshDimension()==2)
3678     {
3679       if(getSpaceDimension()==3)
3680         {
3681           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3682           const double *locPtr=loc->getConstPointer();
3683           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3684             {
3685               int offset=connI[*i];
3686               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3687               double n=INTERP_KERNEL::norm<3>(vals);
3688               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3689             }
3690         }
3691       else
3692         {
3693           for(std::size_t i=0;i<nbelems;i++)
3694             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3695         }
3696     }
3697   else//meshdimension==1
3698     {
3699       double tmp[2];
3700       for(const int *i=begin;i!=end;i++)
3701         {
3702           int offset=connI[*i];
3703           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3704           double n=INTERP_KERNEL::norm<2>(tmp);
3705           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3706           *vals++=-tmp[1];
3707           *vals++=tmp[0];
3708         }
3709     }
3710   ret->setArray(array);
3711   ret->setMesh(this);
3712   ret->synchronizeTimeWithSupport();
3713   return ret.retn();
3714 }
3715
3716 /*!
3717  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3718  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3719  * and are \b not normalized.
3720  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3721  *          cells and one time. The caller is to delete this field using decrRef() as
3722  *          it is no more needed.
3723  *  \throw If the nodal connectivity of cells is not defined.
3724  *  \throw If the coordinates array is not set.
3725  *  \throw If \a this->getMeshDimension() != 1.
3726  *  \throw If \a this mesh includes cells of type other than SEG2.
3727  */
3728 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3729 {
3730   if(getMeshDimension()!=1)
3731     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3732   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3733     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3734   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3735   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3736   int nbOfCells=getNumberOfCells();
3737   int spaceDim=getSpaceDimension();
3738   array->alloc(nbOfCells,spaceDim);
3739   double *pt=array->getPointer();
3740   const double *coo=getCoords()->getConstPointer();
3741   std::vector<int> conn;
3742   conn.reserve(2);
3743   for(int i=0;i<nbOfCells;i++)
3744     {
3745       conn.resize(0);
3746       getNodeIdsOfCell(i,conn);
3747       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3748     }
3749   ret->setArray(array);
3750   ret->setMesh(this);
3751   ret->synchronizeTimeWithSupport();
3752   return ret.retn();
3753 }
3754
3755 /*!
3756  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3757  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3758  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3759  * from. If a result face is shared by two 3D cells, then the face in included twice in
3760  * the result mesh.
3761  *  \param [in] origin - 3 components of a point defining location of the plane.
3762  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3763  *         must be greater than 1e-6.
3764  *  \param [in] eps - half-thickness of the plane.
3765  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3766  *         producing correspondent 2D cells. The caller is to delete this array
3767  *         using decrRef() as it is no more needed.
3768  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3769  *         not share the node coordinates array with \a this mesh. The caller is to
3770  *         delete this mesh using decrRef() as it is no more needed.  
3771  *  \throw If the coordinates array is not set.
3772  *  \throw If the nodal connectivity of cells is not defined.
3773  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3774  *  \throw If magnitude of \a vec is less than 1e-6.
3775  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3776  *  \throw If \a this includes quadratic cells.
3777  */
3778 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3779 {
3780   checkFullyDefined();
3781   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3782     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3783   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3784   if(candidates->empty())
3785     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3786   std::vector<int> nodes;
3787   DataArrayInt *cellIds1D=0;
3788   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3789   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3790   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3791   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3792   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3793   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3794   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3795   revDesc2=0; revDescIndx2=0;
3796   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3797   revDesc1=0; revDescIndx1=0;
3798   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3799   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3800   //
3801   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3802   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3803     cut3DCurve[*it]=-1;
3804   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3805   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3806   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3807                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3808                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3809   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3810   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3811   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3812   if(cellIds2->empty())
3813     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3814   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3815   ret->setCoords(mDesc1->getCoords());
3816   ret->setConnectivity(conn,connI,true);
3817   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3818   return ret.retn();
3819 }
3820
3821 /*!
3822  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3823 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
3824 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3825 the result mesh.
3826  *  \param [in] origin - 3 components of a point defining location of the plane.
3827  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3828  *         must be greater than 1e-6.
3829  *  \param [in] eps - half-thickness of the plane.
3830  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3831  *         producing correspondent segments. The caller is to delete this array
3832  *         using decrRef() as it is no more needed.
3833  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3834  *         mesh in 3D space. This mesh does not share the node coordinates array with
3835  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3836  *         no more needed. 
3837  *  \throw If the coordinates array is not set.
3838  *  \throw If the nodal connectivity of cells is not defined.
3839  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3840  *  \throw If magnitude of \a vec is less than 1e-6.
3841  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3842  *  \throw If \a this includes quadratic cells.
3843  */
3844 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3845 {
3846   checkFullyDefined();
3847   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3848     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3849   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3850   if(candidates->empty())
3851     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3852   std::vector<int> nodes;
3853   DataArrayInt *cellIds1D=0;
3854   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3855   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3856   MCAuto<DataArrayInt> desc1=DataArrayInt::New();
3857   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New();
3858   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New();
3859   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New();
3860   MCAuto<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3861   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3862   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3863   //
3864   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3865   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3866     cut3DCurve[*it]=-1;
3867   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3868   int ncellsSub=subMesh->getNumberOfCells();
3869   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3870   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3871                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3872                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3873   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3874   conn->alloc(0,1);
3875   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3876   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3877   for(int i=0;i<ncellsSub;i++)
3878     {
3879       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3880         {
3881           if(cut3DSurf[i].first!=-2)
3882             {
3883               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3884               connI->pushBackSilent(conn->getNumberOfTuples());
3885               cellIds2->pushBackSilent(i);
3886             }
3887           else
3888             {
3889               int cellId3DSurf=cut3DSurf[i].second;
3890               int offset=nodalI[cellId3DSurf]+1;
3891               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3892               for(int j=0;j<nbOfEdges;j++)
3893                 {
3894                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3895                   connI->pushBackSilent(conn->getNumberOfTuples());
3896                   cellIds2->pushBackSilent(cellId3DSurf);
3897                 }
3898             }
3899         }
3900     }
3901   if(cellIds2->empty())
3902     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3903   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3904   ret->setCoords(mDesc1->getCoords());
3905   ret->setConnectivity(conn,connI,true);
3906   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3907   return ret.retn();
3908 }
3909
3910 /*!
3911  * Finds cells whose bounding boxes intersect a given plane.
3912  *  \param [in] origin - 3 components of a point defining location of the plane.
3913  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3914  *         must be greater than 1e-6.
3915  *  \param [in] eps - half-thickness of the plane.
3916  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3917  *         cells. The caller is to delete this array using decrRef() as it is no more
3918  *         needed.
3919  *  \throw If the coordinates array is not set.
3920  *  \throw If the nodal connectivity of cells is not defined.
3921  *  \throw If \a this->getSpaceDimension() != 3.
3922  *  \throw If magnitude of \a vec is less than 1e-6.
3923  *  \sa buildSlice3D()
3924  */
3925 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3926 {
3927   checkFullyDefined();
3928   if(getSpaceDimension()!=3)
3929     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3930   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3931   if(normm<1e-6)
3932     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3933   double vec2[3];
3934   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3935   double angle=acos(vec[2]/normm);
3936   MCAuto<DataArrayInt> cellIds;
3937   double bbox[6];
3938   if(angle>eps)
3939     {
3940       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
3941       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3942       if(normm2/normm>1e-6)
3943         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3944       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3945       mw->setCoords(coo);
3946       mw->getBoundingBox(bbox);
3947       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3948       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3949     }
3950   else
3951     {
3952       getBoundingBox(bbox);
3953       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3954       cellIds=getCellsInBoundingBox(bbox,eps);
3955     }
3956   return cellIds.retn();
3957 }
3958
3959 /*!
3960  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3961  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3962  * No consideration of coordinate is done by this method.
3963  * 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)
3964  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull.
3965  */
3966 bool MEDCouplingUMesh::isContiguous1D() const
3967 {
3968   if(getMeshDimension()!=1)
3969     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3970   int nbCells=getNumberOfCells();
3971   if(nbCells<1)
3972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3973   const int *connI=_nodal_connec_index->getConstPointer();
3974   const int *conn=_nodal_connec->getConstPointer();
3975   int ref=conn[connI[0]+2];
3976   for(int i=1;i<nbCells;i++)
3977     {
3978       if(conn[connI[i]+1]!=ref)
3979         return false;
3980       ref=conn[connI[i]+2];
3981     }
3982   return true;
3983 }
3984
3985 /*!
3986  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3987  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3988  * \param pt reference point of the line
3989  * \param v normalized director vector of the line
3990  * \param eps max precision before throwing an exception
3991  * \param res output of size this->getNumberOfCells
3992  */
3993 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3994 {
3995   if(getMeshDimension()!=1)
3996     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3997   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3998     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3999   if(getSpaceDimension()!=3)
4000     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4001   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4002   const double *fPtr=f->getArray()->getConstPointer();
4003   double tmp[3];
4004   for(int i=0;i<getNumberOfCells();i++)
4005     {
4006       const double *tmp1=fPtr+3*i;
4007       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4008       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4009       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4010       double n1=INTERP_KERNEL::norm<3>(tmp);
4011       n1/=INTERP_KERNEL::norm<3>(tmp1);
4012       if(n1>eps)
4013         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4014     }
4015   const double *coo=getCoords()->getConstPointer();
4016   for(int i=0;i<getNumberOfNodes();i++)
4017     {
4018       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4019       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4020       res[i]=std::accumulate(tmp,tmp+3,0.);
4021     }
4022 }
4023
4024 /*!
4025  * 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. 
4026  * \a this is expected to be a mesh so that its space dimension is equal to its
4027  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4028  * 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).
4029  *
4030  * 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
4031  * 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).
4032  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4033  *
4034  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4035  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4036  *
4037  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4038  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4039  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4040  * \return the positive value of the distance.
4041  * \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
4042  * dimension - 1.
4043  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4044  */
4045 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4046 {
4047   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4048   if(meshDim!=spaceDim-1)
4049     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4050   if(meshDim!=2 && meshDim!=1)
4051     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4052   checkFullyDefined();
4053   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4054     { 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()); }
4055   DataArrayInt *ret1=0;
4056   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4057   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4058   MCAuto<DataArrayInt> ret1Safe(ret1);
4059   cellId=*ret1Safe->begin();
4060   return *ret0->begin();
4061 }
4062
4063 /*!
4064  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4065  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4066  * 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
4067  * 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).
4068  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4069  * 
4070  * \a this is expected to be a mesh so that its space dimension is equal to its
4071  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4072  * 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).
4073  *
4074  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4075  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4076  *
4077  * \param [in] pts the list of points in which each tuple represents a point
4078  * \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.
4079  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4080  * \throw if number of components of \a pts is not equal to the space dimension.
4081  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4082  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4083  */
4084 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4085 {
4086   if(!pts)
4087     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4088   pts->checkAllocated();
4089   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4090   if(meshDim!=spaceDim-1)
4091     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4092   if(meshDim!=2 && meshDim!=1)
4093     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4094   if(pts->getNumberOfComponents()!=spaceDim)
4095     {
4096       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4097       throw INTERP_KERNEL::Exception(oss.str().c_str());
4098     }
4099   checkFullyDefined();
4100   int nbCells=getNumberOfCells();
4101   if(nbCells==0)
4102     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4103   int nbOfPts=pts->getNumberOfTuples();
4104   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4105   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4106   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4107   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4108   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4109   const double *bbox(bboxArr->begin());
4110   switch(spaceDim)
4111   {
4112     case 3:
4113       {
4114         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4115         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4116           {
4117             double x=std::numeric_limits<double>::max();
4118             std::vector<int> elems;
4119             myTree.getMinDistanceOfMax(ptsPtr,x);
4120             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4121             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4122           }
4123         break;
4124       }
4125     case 2:
4126       {
4127         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4128         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4129           {
4130             double x=std::numeric_limits<double>::max();
4131             std::vector<int> elems;
4132             myTree.getMinDistanceOfMax(ptsPtr,x);
4133             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4134             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4135           }
4136         break;
4137       }
4138     default:
4139       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4140   }
4141   cellIds=ret1.retn();
4142   return ret0.retn();
4143 }
4144
4145 /// @cond INTERNAL
4146
4147 /*!
4148  * \param [in] pt the start pointer (included) of the coordinates of the point
4149  * \param [in] cellIdsBg the start pointer (included) of cellIds
4150  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4151  * \param [in] nc nodal connectivity
4152  * \param [in] ncI nodal connectivity index
4153  * \param [in,out] ret0 the min distance between \a this and the external input point
4154  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4155  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4156  */
4157 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)
4158 {
4159   cellId=-1;
4160   ret0=std::numeric_limits<double>::max();
4161   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4162     {
4163       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4164       {
4165         case INTERP_KERNEL::NORM_TRI3:
4166           {
4167             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4168             if(tmp<ret0)
4169               { ret0=tmp; cellId=*zeCell; }
4170             break;
4171           }
4172         case INTERP_KERNEL::NORM_QUAD4:
4173         case INTERP_KERNEL::NORM_POLYGON:
4174           {
4175             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4176             if(tmp<ret0)
4177               { ret0=tmp; cellId=*zeCell; }
4178             break;
4179           }
4180         default:
4181           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4182       }
4183     }
4184 }
4185
4186 /*!
4187  * \param [in] pt the start pointer (included) of the coordinates of the point
4188  * \param [in] cellIdsBg the start pointer (included) of cellIds
4189  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4190  * \param [in] nc nodal connectivity
4191  * \param [in] ncI nodal connectivity index
4192  * \param [in,out] ret0 the min distance between \a this and the external input point
4193  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4194  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4195  */
4196 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)
4197 {
4198   cellId=-1;
4199   ret0=std::numeric_limits<double>::max();
4200   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4201     {
4202       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4203       {
4204         case INTERP_KERNEL::NORM_SEG2:
4205           {
4206             std::size_t uselessEntry=0;
4207             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4208             tmp=sqrt(tmp);
4209             if(tmp<ret0)
4210               { ret0=tmp; cellId=*zeCell; }
4211             break;
4212           }
4213         default:
4214           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4215       }
4216     }
4217 }
4218 /// @endcond
4219
4220 /*!
4221  * Finds cells in contact with a ball (i.e. a point with precision). 
4222  * 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.
4223  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4224  *
4225  * \warning This method is suitable if the caller intends to evaluate only one
4226  *          point, for more points getCellsContainingPoints() is recommended as it is
4227  *          faster. 
4228  *  \param [in] pos - array of coordinates of the ball central point.
4229  *  \param [in] eps - ball radius.
4230  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4231  *         if there are no such cells.
4232  *  \throw If the coordinates array is not set.
4233  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4234  */
4235 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4236 {
4237   std::vector<int> elts;
4238   getCellsContainingPoint(pos,eps,elts);
4239   if(elts.empty())
4240     return -1;
4241   return elts.front();
4242 }
4243
4244 /*!
4245  * Finds cells in contact with a ball (i.e. a point with precision).
4246  * 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.
4247  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4248  * \warning This method is suitable if the caller intends to evaluate only one
4249  *          point, for more points getCellsContainingPoints() is recommended as it is
4250  *          faster. 
4251  *  \param [in] pos - array of coordinates of the ball central point.
4252  *  \param [in] eps - ball radius.
4253  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4254  *         before inserting ids.
4255  *  \throw If the coordinates array is not set.
4256  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4257  *
4258  *  \if ENABLE_EXAMPLES
4259  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4260  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4261  *  \endif
4262  */
4263 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4264 {
4265   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4266   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4267   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4268 }
4269
4270 /// @cond INTERNAL
4271
4272 namespace MEDCoupling
4273 {
4274   template<const int SPACEDIMM>
4275   class DummyClsMCUG
4276   {
4277   public:
4278     static const int MY_SPACEDIM=SPACEDIMM;
4279     static const int MY_MESHDIM=8;
4280     typedef int MyConnType;
4281     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4282     // begin
4283     // useless, but for windows compilation ...
4284     const double* getCoordinatesPtr() const { return 0; }
4285     const int* getConnectivityPtr() const { return 0; }
4286     const int* getConnectivityIndexPtr() const { return 0; }
4287     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4288     // end
4289   };
4290
4291   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MCAuto<INTERP_KERNEL::Node>,int>& m)
4292   {
4293     INTERP_KERNEL::Edge *ret(0);
4294     MCAuto<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]));
4295     m[n0]=bg[0]; m[n1]=bg[1];
4296     switch(typ)
4297     {
4298       case INTERP_KERNEL::NORM_SEG2:
4299         {
4300           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4301           break;
4302         }
4303       case INTERP_KERNEL::NORM_SEG3:
4304         {
4305           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4306           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4307           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4308           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4309           bool colinearity(inters.areColinears());
4310           delete e1; delete e2;
4311           if(colinearity)
4312             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4313           else
4314             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4315           break;
4316         }
4317       default:
4318         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4319     }
4320     return ret;
4321   }
4322
4323   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4324   {
4325     INTERP_KERNEL::Edge *ret=0;
4326     switch(typ)
4327     {
4328       case INTERP_KERNEL::NORM_SEG2:
4329         {
4330           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4331           break;
4332         }
4333       case INTERP_KERNEL::NORM_SEG3:
4334         {
4335           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4336           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4337           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4338           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4339           bool colinearity=inters.areColinears();
4340           delete e1; delete e2;
4341           if(colinearity)
4342             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4343           else
4344             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4345           mapp2[bg[2]].second=false;
4346           break;
4347         }
4348       default:
4349         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4350     }
4351     return ret;
4352   }
4353
4354   /*!
4355    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4356    * the global mesh 'mDesc'.
4357    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4358    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4359    */
4360   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4361                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4362   {
4363     mapp.clear();
4364     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.
4365     const double *coo=mDesc->getCoords()->getConstPointer();
4366     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4367     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4368     std::set<int> s;
4369     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4370       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4371     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4372       {
4373         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4374         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4375       }
4376     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4377     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4378       {
4379         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4380         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4381       }
4382     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4383       {
4384         if((*it2).second.second)
4385           mapp[(*it2).second.first]=(*it2).first;
4386         ((*it2).second.first)->decrRef();
4387       }
4388     return ret;
4389   }
4390
4391   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4392   {
4393     if(nodeId>=offset2)
4394       {
4395         int locId=nodeId-offset2;
4396         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4397       }
4398     if(nodeId>=offset1)
4399       {
4400         int locId=nodeId-offset1;
4401         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4402       }
4403     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4404   }
4405
4406   /**
4407    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4408    */
4409   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4410                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4411                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4412   {
4413     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4414       {
4415         int eltId1=abs(*desc1)-1;
4416         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4417           {
4418             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4419             if(it==mappRev.end())
4420               {
4421                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4422                 mapp[node]=*it1;
4423                 mappRev[*it1]=node;
4424               }
4425           }
4426       }
4427   }
4428 }
4429
4430 /// @endcond
4431
4432 template<int SPACEDIM>
4433 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4434                                                    double eps, MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4435 {
4436   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4437   int *eltsIndexPtr(eltsIndex->getPointer());
4438   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4439   const double *bbox(bboxArr->begin());
4440   int nbOfCells=getNumberOfCells();
4441   const int *conn=_nodal_connec->getConstPointer();
4442   const int *connI=_nodal_connec_index->getConstPointer();
4443   double bb[2*SPACEDIM];
4444   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4445   for(int i=0;i<nbOfPoints;i++)
4446     {
4447       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4448       for(int j=0;j<SPACEDIM;j++)
4449         {
4450           bb[2*j]=pos[SPACEDIM*i+j];
4451           bb[2*j+1]=pos[SPACEDIM*i+j];
4452         }
4453       std::vector<int> candidates;
4454       myTree.getIntersectingElems(bb,candidates);
4455       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4456         {
4457           int sz(connI[(*iter)+1]-connI[*iter]-1);
4458           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4459           bool status(false);
4460           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4461             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4462           else
4463             {
4464               if(SPACEDIM!=2)
4465                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4466               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4467               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4468               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4469               INTERP_KERNEL::QuadraticPolygon *pol(0);
4470               for(int j=0;j<sz;j++)
4471                 {
4472                   int nodeId(conn[connI[*iter]+1+j]);
4473                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4474                 }
4475               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4476                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4477               else
4478                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4479               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4480               double a(0.),b(0.),c(0.);
4481               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4482               status=pol->isInOrOut2(n);
4483               delete pol; n->decrRef();
4484             }
4485           if(status)
4486             {
4487               eltsIndexPtr[i+1]++;
4488               elts->pushBackSilent(*iter);
4489             }
4490         }
4491     }
4492 }
4493 /*!
4494  * Finds cells in contact with several balls (i.e. points with precision).
4495  * This method is an extension of getCellContainingPoint() and
4496  * getCellsContainingPoint() for the case of multiple points.
4497  * 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.
4498  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4499  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4500  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4501  *         this->getSpaceDimension() * \a nbOfPoints 
4502  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4503  *  \param [in] eps - radius of balls (i.e. the precision).
4504  *  \param [out] elts - vector returning ids of found cells.
4505  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4506  *         dividing cell ids in \a elts into groups each referring to one
4507  *         point. Its every element (except the last one) is an index pointing to the
4508  *         first id of a group of cells. For example cells in contact with the *i*-th
4509  *         point are described by following range of indices:
4510  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4511  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4512  *         Number of cells in contact with the *i*-th point is
4513  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4514  *  \throw If the coordinates array is not set.
4515  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4516  *
4517  *  \if ENABLE_EXAMPLES
4518  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4519  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4520  *  \endif
4521  */
4522 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4523                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4524 {
4525   int spaceDim=getSpaceDimension();
4526   int mDim=getMeshDimension();
4527   if(spaceDim==3)
4528     {
4529       if(mDim==3)
4530         {
4531           const double *coords=_coords->getConstPointer();
4532           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4533         }
4534       /*else if(mDim==2)
4535         {
4536
4537         }*/
4538       else
4539         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4540     }
4541   else if(spaceDim==2)
4542     {
4543       if(mDim==2)
4544         {
4545           const double *coords=_coords->getConstPointer();
4546           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4547         }
4548       else
4549         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4550     }
4551   else if(spaceDim==1)
4552     {
4553       if(mDim==1)
4554         {
4555           const double *coords=_coords->getConstPointer();
4556           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4557         }
4558       else
4559         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4560     }
4561   else
4562     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4563 }
4564
4565 /*!
4566  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4567  * least two its edges intersect each other anywhere except their extremities. An
4568  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4569  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4570  *         cleared before filling in.
4571  *  \param [in] eps - precision.
4572  *  \throw If \a this->getMeshDimension() != 2.
4573  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4574  */
4575 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4576 {
4577   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4578   if(getMeshDimension()!=2)
4579     throw INTERP_KERNEL::Exception(msg);
4580   int spaceDim=getSpaceDimension();
4581   if(spaceDim!=2 && spaceDim!=3)
4582     throw INTERP_KERNEL::Exception(msg);
4583   const int *conn=_nodal_connec->getConstPointer();
4584   const int *connI=_nodal_connec_index->getConstPointer();
4585   int nbOfCells=getNumberOfCells();
4586   std::vector<double> cell2DinS2;
4587   for(int i=0;i<nbOfCells;i++)
4588     {
4589       int offset=connI[i];
4590       int nbOfNodesForCell=connI[i+1]-offset-1;
4591       if(nbOfNodesForCell<=3)
4592         continue;
4593       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4594       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4595       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4596         cells.push_back(i);
4597       cell2DinS2.clear();
4598     }
4599 }
4600
4601 /*!
4602  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4603  *
4604  * 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.
4605  * 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.
4606  * 
4607  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4608  * This convex envelop is computed using Jarvis march algorithm.
4609  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4610  * 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)
4611  * 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.
4612  *
4613  * \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.
4614  * \sa MEDCouplingUMesh::colinearize2D
4615  */
4616 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4617 {
4618   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4619     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4620   checkFullyDefined();
4621   const double *coords=getCoords()->getConstPointer();
4622   int nbOfCells=getNumberOfCells();
4623   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4624   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4625   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4626   int *workIndexOut=nodalConnecIndexOut->getPointer();
4627   *workIndexOut=0;
4628   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4629   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4630   std::set<INTERP_KERNEL::NormalizedCellType> types;
4631   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4632   isChanged->alloc(0,1);
4633   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4634     {
4635       int pos=nodalConnecOut->getNumberOfTuples();
4636       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4637         isChanged->pushBackSilent(i);
4638       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4639       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4640     }
4641   if(isChanged->empty())
4642     return 0;
4643   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4644   _types=types;
4645   return isChanged.retn();
4646 }
4647
4648 /*!
4649  * This method is \b NOT const because it can modify \a this.
4650  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4651  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4652  * \param policy specifies the type of extrusion chosen:
4653  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4654  *   will be repeated to build each level
4655  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4656  *   the 3 preceding points of the 1D mesh. The center of the arc is the center of rotation for each level, the rotation is done
4657  *   along an axis normal to the plane containing the arc, and finally the angle of rotation is defined by the first two points on the
4658  *   arc.
4659  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4660  */
4661 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4662 {
4663   checkFullyDefined();
4664   mesh1D->checkFullyDefined();
4665   if(!mesh1D->isContiguous1D())
4666     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4667   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4668     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4669   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4670     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4671   if(mesh1D->getMeshDimension()!=1)
4672     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4673   bool isQuad=false;
4674   if(isPresenceOfQuadratic())
4675     {
4676       if(mesh1D->isFullyQuadratic())
4677         isQuad=true;
4678       else
4679         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4680     }
4681   int oldNbOfNodes(getNumberOfNodes());
4682   MCAuto<DataArrayDouble> newCoords;
4683   switch(policy)
4684   {
4685     case 0:
4686       {
4687         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4688         break;
4689       }
4690     case 1:
4691       {
4692         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4693         break;
4694       }
4695     default:
4696       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4697   }
4698   setCoords(newCoords);
4699   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4700   updateTime();
4701   return ret.retn();
4702 }
4703
4704 /*!
4705  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4706  * If it is not the case an exception will be thrown.
4707  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4708  * intersection of plane defined by ('origin','vec').
4709  * This method has one in/out parameter : 'cut3DCurve'.
4710  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4711  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4712  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4713  * This method will throw an exception if \a this contains a non linear segment.
4714  */
4715 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4716 {
4717   checkFullyDefined();
4718   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4719     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4720   int ncells=getNumberOfCells();
4721   int nnodes=getNumberOfNodes();
4722   double vec2[3],vec3[3],vec4[3];
4723   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4724   if(normm<1e-6)
4725     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4726   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4727   const int *conn=_nodal_connec->getConstPointer();
4728   const int *connI=_nodal_connec_index->getConstPointer();
4729   const double *coo=_coords->getConstPointer();
4730   std::vector<double> addCoo;
4731   for(int i=0;i<ncells;i++)
4732     {
4733       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4734         {
4735           if(cut3DCurve[i]==-2)
4736             {
4737               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4738               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];
4739               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4740               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4741               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4742                 {
4743                   const double *st2=coo+3*st;
4744                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4745                   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]));
4746                   if(pos>eps && pos<1-eps)
4747                     {
4748                       int nNode=((int)addCoo.size())/3;
4749                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4750                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4751                       cut3DCurve[i]=nnodes+nNode;
4752                     }
4753                 }
4754             }
4755         }
4756       else
4757         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4758     }
4759   if(!addCoo.empty())
4760     {
4761       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4762       MCAuto<DataArrayDouble> coo2=DataArrayDouble::New();
4763       coo2->alloc(newNbOfNodes,3);
4764       double *tmp=coo2->getPointer();
4765       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4766       std::copy(addCoo.begin(),addCoo.end(),tmp);
4767       DataArrayDouble::SetArrayIn(coo2,_coords);
4768     }
4769 }
4770
4771 /*!
4772  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4773  * \param mesh1D is the input 1D mesh used for translation computation.
4774  * \return newCoords new coords filled by this method. 
4775  */
4776 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4777 {
4778   int oldNbOfNodes=getNumberOfNodes();
4779   int nbOf1DCells=mesh1D->getNumberOfCells();
4780   int spaceDim=getSpaceDimension();
4781   DataArrayDouble *ret=DataArrayDouble::New();
4782   std::vector<bool> isQuads;
4783   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4784   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4785   double *retPtr=ret->getPointer();
4786   const double *coords=getCoords()->getConstPointer();
4787   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4788   std::vector<int> v;
4789   std::vector<double> c;
4790   double vec[3];
4791   v.reserve(3);
4792   c.reserve(6);
4793   for(int i=0;i<nbOf1DCells;i++)
4794     {
4795       v.resize(0);
4796       mesh1D->getNodeIdsOfCell(i,v);
4797       c.resize(0);
4798       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4799       mesh1D->getCoordinatesOfNode(v[0],c);
4800       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4801       for(int j=0;j<oldNbOfNodes;j++)
4802         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4803       if(isQuad)
4804         {
4805           c.resize(0);
4806           mesh1D->getCoordinatesOfNode(v[1],c);
4807           mesh1D->getCoordinatesOfNode(v[0],c);
4808           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4809           for(int j=0;j<oldNbOfNodes;j++)
4810             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4811         }
4812     }
4813   ret->copyStringInfoFrom(*getCoords());
4814   return ret;
4815 }
4816
4817 /*!
4818  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4819  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4820  * \return newCoords new coords filled by this method. 
4821  */
4822 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4823 {
4824   if(mesh1D->getSpaceDimension()==2)
4825     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4826   if(mesh1D->getSpaceDimension()==3)
4827     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4828   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4829 }
4830
4831 /*!
4832  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4833  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4834  * \return newCoords new coords filled by this method. 
4835  */
4836 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4837 {
4838   if(isQuad)
4839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4840   int oldNbOfNodes=getNumberOfNodes();
4841   int nbOf1DCells=mesh1D->getNumberOfCells();
4842   if(nbOf1DCells<2)
4843     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4844   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
4845   int nbOfLevsInVec=nbOf1DCells+1;
4846   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4847   double *retPtr=ret->getPointer();
4848   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4849   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4850   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
4851   tmp->setCoords(tmp2);
4852   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4853   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4854   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4855   for(int i=1;i<nbOfLevsInVec;i++)
4856     {
4857       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4858       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4859       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4860       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4861       tmp->translate(vec);
4862       double tmp3[2],radius,alpha,alpha0;
4863       const double *p0=i+1<nbOfLevsInVec?begin:third;
4864       const double *p1=i+1<nbOfLevsInVec?end:begin;
4865       const double *p2=i+1<nbOfLevsInVec?third:end;
4866       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4867       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]);
4868       double angle=acos(cosangle/(radius*radius));
4869       tmp->rotate(end,0,angle);
4870       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4871     }
4872   return ret.retn();
4873 }
4874
4875 /*!
4876  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4877  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4878  * \return newCoords new coords filled by this method. 
4879  */
4880 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4881 {
4882   if(isQuad)
4883     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4884   int oldNbOfNodes=getNumberOfNodes();
4885   int nbOf1DCells=mesh1D->getNumberOfCells();
4886   if(nbOf1DCells<2)
4887     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4888   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
4889   int nbOfLevsInVec=nbOf1DCells+1;
4890   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4891   double *retPtr=ret->getPointer();
4892   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4893   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4894   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
4895   tmp->setCoords(tmp2);
4896   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4897   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4898   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4899   for(int i=1;i<nbOfLevsInVec;i++)
4900     {
4901       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4902       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4903       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4904       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4905       tmp->translate(vec);
4906       double tmp3[2],radius,alpha,alpha0;
4907       const double *p0=i+1<nbOfLevsInVec?begin:third;
4908       const double *p1=i+1<nbOfLevsInVec?end:begin;
4909       const double *p2=i+1<nbOfLevsInVec?third:end;
4910       double vecPlane[3]={
4911         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4912         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4913         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4914       };
4915       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4916       if(norm>1.e-7)
4917         {
4918           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4919           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4920           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4921           double s2=norm2;
4922           double c2=cos(asin(s2));
4923           double m[3][3]={
4924             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4925             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4926             {-vec2[1]*s2, vec2[0]*s2, c2}
4927           };
4928           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]};
4929           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]};
4930           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]};
4931           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4932           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]);
4933           double angle=acos(cosangle/(radius*radius));
4934           tmp->rotate(end,vecPlane,angle);
4935         }
4936       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4937     }
4938   return ret.retn();
4939 }
4940
4941 /*!
4942  * This method is private because not easy to use for end user. This method is const contrary to
4943  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4944  * the coords sorted slice by slice.
4945  * \param isQuad specifies presence of quadratic cells.
4946  */
4947 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4948 {
4949   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4950   int nbOf2DCells(getNumberOfCells());
4951   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4952   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4953   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4954   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4955   newConnI->alloc(nbOf3DCells+1,1);
4956   int *newConnIPtr(newConnI->getPointer());
4957   *newConnIPtr++=0;
4958   std::vector<int> newc;
4959   for(int j=0;j<nbOf2DCells;j++)
4960     {
4961       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4962       *newConnIPtr++=(int)newc.size();
4963     }
4964   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4965   int *newConnPtr(newConn->getPointer());
4966   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4967   newConnIPtr=newConnI->getPointer();
4968   for(int iz=0;iz<nbOf1DCells;iz++)
4969     {
4970       if(iz!=0)
4971         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4972       const int *posOfTypeOfCell(newConnIPtr);
4973       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4974         {
4975           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4976           if(icell!=*posOfTypeOfCell)
4977             {
4978               if(*iter!=-1)
4979                 *newConnPtr=(*iter)+iz*deltaPerLev;
4980               else
4981                 *newConnPtr=-1;
4982             }
4983           else
4984             {
4985               *newConnPtr=*iter;
4986               posOfTypeOfCell++;
4987             }
4988         }
4989     }
4990   ret->setConnectivity(newConn,newConnI,true);
4991   ret->setCoords(getCoords());
4992   return ret;
4993 }
4994
4995 /*!
4996  * Checks if \a this mesh is constituted by only quadratic cells.
4997  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4998  *  \throw If the coordinates array is not set.
4999  *  \throw If the nodal connectivity of cells is not defined.
5000  */
5001 bool MEDCouplingUMesh::isFullyQuadratic() const
5002 {
5003   checkFullyDefined();
5004   bool ret=true;
5005   int nbOfCells=getNumberOfCells();
5006   for(int i=0;i<nbOfCells && ret;i++)
5007     {
5008       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5009       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5010       ret=cm.isQuadratic();
5011     }
5012   return ret;
5013 }
5014
5015 /*!
5016  * Checks if \a this mesh includes any quadratic cell.
5017  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5018  *  \throw If the coordinates array is not set.
5019  *  \throw If the nodal connectivity of cells is not defined.
5020  */
5021 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5022 {
5023   checkFullyDefined();
5024   bool ret=false;
5025   int nbOfCells=getNumberOfCells();
5026   for(int i=0;i<nbOfCells && !ret;i++)
5027     {
5028       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5029       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5030       ret=cm.isQuadratic();
5031     }
5032   return ret;
5033 }
5034
5035 /*!
5036  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5037  * this mesh, it remains unchanged.
5038  *  \throw If the coordinates array is not set.
5039  *  \throw If the nodal connectivity of cells is not defined.
5040  */
5041 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5042 {
5043   checkFullyDefined();
5044   int nbOfCells=getNumberOfCells();
5045   int delta=0;
5046   const int *iciptr=_nodal_connec_index->getConstPointer();
5047   for(int i=0;i<nbOfCells;i++)
5048     {
5049       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5050       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5051       if(cm.isQuadratic())
5052         {
5053           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5054           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5055           if(!cml.isDynamic())
5056             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5057           else
5058             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5059         }
5060     }
5061   if(delta==0)
5062     return ;
5063   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5064   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5065   const int *icptr=_nodal_connec->getConstPointer();
5066   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
5067   newConnI->alloc(nbOfCells+1,1);
5068   int *ocptr=newConn->getPointer();
5069   int *ociptr=newConnI->getPointer();
5070   *ociptr=0;
5071   _types.clear();
5072   for(int i=0;i<nbOfCells;i++,ociptr++)
5073     {
5074       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5075       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5076       if(!cm.isQuadratic())
5077         {
5078           _types.insert(type);
5079           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5080           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5081         }
5082       else
5083         {
5084           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5085           _types.insert(typel);
5086           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5087           int newNbOfNodes=cml.getNumberOfNodes();
5088           if(cml.isDynamic())
5089             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5090           *ocptr++=(int)typel;
5091           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5092           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5093         }
5094     }
5095   setConnectivity(newConn,newConnI,false);
5096 }
5097
5098 /*!
5099  * This method converts all linear cell in \a this to quadratic one.
5100  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5101  * 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)
5102  * 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.
5103  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5104  * end of the existing coordinates.
5105  * 
5106  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5107  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5108  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5109  * 
5110  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5111  *
5112  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5113  */
5114 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5115 {
5116   DataArrayInt *conn=0,*connI=0;
5117   DataArrayDouble *coords=0;
5118   std::set<INTERP_KERNEL::NormalizedCellType> types;
5119   checkFullyDefined();
5120   MCAuto<DataArrayInt> ret,connSafe,connISafe;
5121   MCAuto<DataArrayDouble> coordsSafe;
5122   int meshDim=getMeshDimension();
5123   switch(conversionType)
5124   {
5125     case 0:
5126       switch(meshDim)
5127       {
5128         case 1:
5129           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5130           connSafe=conn; connISafe=connI; coordsSafe=coords;
5131           break;
5132         case 2:
5133           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5134           connSafe=conn; connISafe=connI; coordsSafe=coords;
5135           break;
5136         case 3:
5137           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5138           connSafe=conn; connISafe=connI; coordsSafe=coords;
5139           break;
5140         default:
5141           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5142       }
5143       break;
5144         case 1:
5145           {
5146             switch(meshDim)
5147             {
5148               case 1:
5149                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5150                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5151                 break;
5152               case 2:
5153                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5154                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5155                 break;
5156               case 3:
5157                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5158                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5159                 break;
5160               default:
5161                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5162             }
5163             break;
5164           }
5165         default:
5166           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5167   }
5168   setConnectivity(connSafe,connISafe,false);
5169   _types=types;
5170   setCoords(coordsSafe);
5171   return ret.retn();
5172 }
5173
5174 /*!
5175  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5176  * so that the number of cells remains the same. Quadratic faces are converted to
5177  * polygons. This method works only for 2D meshes in
5178  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5179  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5180  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5181  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5182  *         a polylinized edge constituting the input polygon.
5183  *  \throw If the coordinates array is not set.
5184  *  \throw If the nodal connectivity of cells is not defined.
5185  *  \throw If \a this->getMeshDimension() != 2.
5186  *  \throw If \a this->getSpaceDimension() != 2.
5187  */
5188 void MEDCouplingUMesh::tessellate2D(double eps)
5189 {
5190   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
5191   if(spaceDim!=2)
5192     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
5193   switch(meshDim)
5194     {
5195     case 1:
5196       return tessellate2DCurveInternal(eps);
5197     case 2:
5198       return tessellate2DInternal(eps);
5199     default:
5200       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
5201     }
5202 }
5203 /*!
5204  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5205  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5206  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5207  *         a sub-divided edge.
5208  *  \throw If the coordinates array is not set.
5209  *  \throw If the nodal connectivity of cells is not defined.
5210  *  \throw If \a this->getMeshDimension() != 1.
5211  *  \throw If \a this->getSpaceDimension() != 2.
5212  */
5213
5214 #if 0
5215 /*!
5216  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5217  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5218  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5219  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5220  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5221  * This method can be seen as the opposite method of colinearize2D.
5222  * 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
5223  * to avoid to modify the numbering of existing nodes.
5224  *
5225  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5226  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5227  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5228  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5229  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5230  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5231  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5232  *
5233  * \sa buildDescendingConnectivity2
5234  */
5235 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5236                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5237 {
5238   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5239     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5240   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5241   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5242     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5243   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5244     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5245   //DataArrayInt *out0(0),*outi0(0);
5246   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5247   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
5248   //out0s=out0s->buildUnique(); out0s->sort(true);
5249 }
5250 #endif
5251
5252 /*!
5253  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5254  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5255  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5256  */
5257 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5258 {
5259   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5260   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5261   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5262   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5263   int nbOfCells=getNumberOfCells();
5264   int nbOfNodes=getNumberOfNodes();
5265   const int *cPtr=_nodal_connec->getConstPointer();
5266   const int *icPtr=_nodal_connec_index->getConstPointer();
5267   int lastVal=0,offset=nbOfNodes;
5268   for(int i=0;i<nbOfCells;i++,icPtr++)
5269     {
5270       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5271       if(type==INTERP_KERNEL::NORM_SEG2)
5272         {
5273           types.insert(INTERP_KERNEL::NORM_SEG3);
5274           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5275           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5276           newConn->pushBackSilent(offset++);
5277           lastVal+=4;
5278           newConnI->pushBackSilent(lastVal);
5279           ret->pushBackSilent(i);
5280         }
5281       else
5282         {
5283           types.insert(type);
5284           lastVal+=(icPtr[1]-icPtr[0]);
5285           newConnI->pushBackSilent(lastVal);
5286           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5287         }
5288     }
5289   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5290   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5291   return ret.retn();
5292 }
5293
5294 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
5295 {
5296   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5297   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5298   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5299   //
5300   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5301   DataArrayInt *conn1D=0,*conn1DI=0;
5302   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5303   DataArrayDouble *coordsTmp=0;
5304   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5305   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5306   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5307   const int *c1DPtr=conn1D->begin();
5308   const int *c1DIPtr=conn1DI->begin();
5309   int nbOfCells=getNumberOfCells();
5310   const int *cPtr=_nodal_connec->getConstPointer();
5311   const int *icPtr=_nodal_connec_index->getConstPointer();
5312   int lastVal=0;
5313   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5314     {
5315       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5316       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5317       if(!cm.isQuadratic())
5318         {
5319           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5320           types.insert(typ2); newConn->pushBackSilent(typ2);
5321           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5322           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5323             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5324           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5325           newConnI->pushBackSilent(lastVal);
5326           ret->pushBackSilent(i);
5327         }
5328       else
5329         {
5330           types.insert(typ);
5331           lastVal+=(icPtr[1]-icPtr[0]);
5332           newConnI->pushBackSilent(lastVal);
5333           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5334         }
5335     }
5336   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5337   return ret.retn();
5338 }
5339
5340 /*!
5341  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5342  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5343  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5344  */
5345 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5346 {
5347   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5348   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5349   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5350 }
5351
5352 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5353 {
5354   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5355   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5356   //
5357   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5358   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5359   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5360   //
5361   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5362   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5363   DataArrayInt *conn1D=0,*conn1DI=0;
5364   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5365   DataArrayDouble *coordsTmp=0;
5366   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5367   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5368   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5369   const int *c1DPtr=conn1D->begin();
5370   const int *c1DIPtr=conn1DI->begin();
5371   int nbOfCells=getNumberOfCells();
5372   const int *cPtr=_nodal_connec->getConstPointer();
5373   const int *icPtr=_nodal_connec_index->getConstPointer();
5374   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5375   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5376     {
5377       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5378       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5379       if(!cm.isQuadratic())
5380         {
5381           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5382           types.insert(typ2); newConn->pushBackSilent(typ2);
5383           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5384           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5385             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5386           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5387           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5388           newConnI->pushBackSilent(lastVal);
5389           ret->pushBackSilent(i);
5390         }
5391       else
5392         {
5393           types.insert(typ);
5394           lastVal+=(icPtr[1]-icPtr[0]);
5395           newConnI->pushBackSilent(lastVal);
5396           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5397         }
5398     }
5399   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5400   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5401   return ret.retn();
5402 }
5403
5404 /*!
5405  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5406  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5407  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5408  */
5409 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5410 {
5411   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5412   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5413   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5414 }
5415
5416 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5417 {
5418   MCAuto<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5419   MCAuto<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5420   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5421   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5422   //
5423   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5424   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5425   MCAuto<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5426   //
5427   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5428   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5429   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5430   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5431   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5432   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5433   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5434   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5435   MCAuto<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5436   MCAuto<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5437   MCAuto<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5438   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5439   int nbOfCells=getNumberOfCells();
5440   const int *cPtr=_nodal_connec->getConstPointer();
5441   const int *icPtr=_nodal_connec_index->getConstPointer();
5442   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5443   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5444     {
5445       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5446       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5447       if(!cm.isQuadratic())
5448         {
5449           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5450           if(typ2==INTERP_KERNEL::NORM_ERROR)
5451             {
5452               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5453               throw INTERP_KERNEL::Exception(oss.str().c_str());
5454             }
5455           types.insert(typ2); newConn->pushBackSilent(typ2);
5456           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5457           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5458             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5459           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5460             {
5461               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5462               int tmpPos=newConn->getNumberOfTuples();
5463               newConn->pushBackSilent(nodeId2);
5464               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5465             }
5466           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5467           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5468           newConnI->pushBackSilent(lastVal);
5469           ret->pushBackSilent(i);
5470         }
5471       else
5472         {
5473           types.insert(typ);
5474           lastVal+=(icPtr[1]-icPtr[0]);
5475           newConnI->pushBackSilent(lastVal);
5476           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5477         }
5478     }
5479   MCAuto<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5480   MCAuto<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5481   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5482   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5483   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5484   int *c=newConn->getPointer();
5485   const int *cI(newConnI->begin());
5486   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5487     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5488   offset=coordsTmp2Safe->getNumberOfTuples();
5489   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5490     c[cI[(*elt)+1]-1]+=offset;
5491   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5492   return ret.retn();
5493 }
5494
5495 /*!
5496  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5497  * In addition, returns an array mapping new cells to old ones. <br>
5498  * This method typically increases the number of cells in \a this mesh
5499  * but the number of nodes remains \b unchanged.
5500  * That's why the 3D splitting policies
5501  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5502  *  \param [in] policy - specifies a pattern used for splitting.
5503  * The semantic of \a policy is:
5504  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5505  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5506  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5507  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5508  *
5509  *
5510  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5511  *          an id of old cell producing it. The caller is to delete this array using
5512  *         decrRef() as it is no more needed.
5513  *
5514  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5515  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5516  *          and \a this->getMeshDimension() != 3. 
5517  *  \throw If \a policy is not one of the four discussed above.
5518  *  \throw If the nodal connectivity of cells is not defined.
5519  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5520  */
5521 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5522 {
5523   switch(policy)
5524   {
5525     case 0:
5526       return simplexizePol0();
5527     case 1:
5528       return simplexizePol1();
5529     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5530         return simplexizePlanarFace5();
5531     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5532         return simplexizePlanarFace6();
5533     default:
5534       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)");
5535   }
5536 }
5537
5538 /*!
5539  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5540  * - 1D: INTERP_KERNEL::NORM_SEG2
5541  * - 2D: INTERP_KERNEL::NORM_TRI3
5542  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5543  *
5544  * This method is useful for users that need to use P1 field services as
5545  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5546  * All these methods need mesh support containing only simplex cells.
5547  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5548  *  \throw If the coordinates array is not set.
5549  *  \throw If the nodal connectivity of cells is not defined.
5550  *  \throw If \a this->getMeshDimension() < 1.
5551  */
5552 bool MEDCouplingUMesh::areOnlySimplexCells() const
5553 {
5554   checkFullyDefined();
5555   int mdim=getMeshDimension();
5556   if(mdim<1 || mdim>3)
5557     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5558   int nbCells=getNumberOfCells();
5559   const int *conn=_nodal_connec->getConstPointer();
5560   const int *connI=_nodal_connec_index->getConstPointer();
5561   for(int i=0;i<nbCells;i++)
5562     {
5563       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5564       if(!cm.isSimplex())
5565         return false;
5566     }
5567   return true;
5568 }
5569
5570 /*!
5571  * This method implements policy 0 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5572  */
5573 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5574 {
5575   checkConnectivityFullyDefined();
5576   if(getMeshDimension()!=2)
5577     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5578   int nbOfCells=getNumberOfCells();
5579   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5580   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5581   ret->alloc(nbOfCells+nbOfCutCells,1);
5582   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5583   int *retPt=ret->getPointer();
5584   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5585   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5586   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5587   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5588   int *pt=newConn->getPointer();
5589   int *ptI=newConnI->getPointer();
5590   ptI[0]=0;
5591   const int *oldc=_nodal_connec->getConstPointer();
5592   const int *ci=_nodal_connec_index->getConstPointer();
5593   for(int i=0;i<nbOfCells;i++,ci++)
5594     {
5595       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5596         {
5597           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5598             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5599           pt=std::copy(tmp,tmp+8,pt);
5600           ptI[1]=ptI[0]+4;
5601           ptI[2]=ptI[0]+8;
5602           *retPt++=i;
5603           *retPt++=i;
5604           ptI+=2;
5605         }
5606       else
5607         {
5608           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5609           ptI[1]=ptI[0]+ci[1]-ci[0];
5610           ptI++;
5611           *retPt++=i;
5612         }
5613     }
5614   _nodal_connec->decrRef();
5615   _nodal_connec=newConn.retn();
5616   _nodal_connec_index->decrRef();
5617   _nodal_connec_index=newConnI.retn();
5618   computeTypes();
5619   updateTime();
5620   return ret.retn();
5621 }
5622
5623 /*!
5624  * This method implements policy 1 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5625  */
5626 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5627 {
5628   checkConnectivityFullyDefined();
5629   if(getMeshDimension()!=2)
5630     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5631   int nbOfCells=getNumberOfCells();
5632   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5633   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5634   ret->alloc(nbOfCells+nbOfCutCells,1);
5635   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5636   int *retPt=ret->getPointer();
5637   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5638   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5639   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5640   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5641   int *pt=newConn->getPointer();
5642   int *ptI=newConnI->getPointer();
5643   ptI[0]=0;
5644   const int *oldc=_nodal_connec->getConstPointer();
5645   const int *ci=_nodal_connec_index->getConstPointer();
5646   for(int i=0;i<nbOfCells;i++,ci++)
5647     {
5648       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5649         {
5650           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5651             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5652           pt=std::copy(tmp,tmp+8,pt);
5653           ptI[1]=ptI[0]+4;
5654           ptI[2]=ptI[0]+8;
5655           *retPt++=i;
5656           *retPt++=i;
5657           ptI+=2;
5658         }
5659       else
5660         {
5661           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5662           ptI[1]=ptI[0]+ci[1]-ci[0];
5663           ptI++;
5664           *retPt++=i;
5665         }
5666     }
5667   _nodal_connec->decrRef();
5668   _nodal_connec=newConn.retn();
5669   _nodal_connec_index->decrRef();
5670   _nodal_connec_index=newConnI.retn();
5671   computeTypes();
5672   updateTime();
5673   return ret.retn();
5674 }
5675
5676 /*!
5677  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5678  */
5679 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5680 {
5681   checkConnectivityFullyDefined();
5682   if(getMeshDimension()!=3)
5683     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5684   int nbOfCells=getNumberOfCells();
5685   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5686   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5687   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5688   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5689   int *retPt=ret->getPointer();
5690   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5691   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5692   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5693   newConn->alloc(getNodalConnectivityArrayLen()+16*nbOfCutCells,1);//21
5694   int *pt=newConn->getPointer();
5695   int *ptI=newConnI->getPointer();
5696   ptI[0]=0;
5697   const int *oldc=_nodal_connec->getConstPointer();
5698   const int *ci=_nodal_connec_index->getConstPointer();
5699   for(int i=0;i<nbOfCells;i++,ci++)
5700     {
5701       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5702         {
5703           for(int j=0;j<5;j++,pt+=5,ptI++)
5704             {
5705               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5706               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];
5707               *retPt++=i;
5708               ptI[1]=ptI[0]+5;
5709             }
5710         }
5711       else
5712         {
5713           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5714           ptI[1]=ptI[0]+ci[1]-ci[0];
5715           ptI++;
5716           *retPt++=i;
5717         }
5718     }
5719   _nodal_connec->decrRef();
5720   _nodal_connec=newConn.retn();
5721   _nodal_connec_index->decrRef();
5722   _nodal_connec_index=newConnI.retn();
5723   computeTypes();
5724   updateTime();
5725   return ret.retn();
5726 }
5727
5728 /*!
5729  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5730  */
5731 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5732 {
5733   checkConnectivityFullyDefined();
5734   if(getMeshDimension()!=3)
5735     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5736   int nbOfCells=getNumberOfCells();
5737   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5738   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5739   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5740   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5741   int *retPt=ret->getPointer();
5742   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5743   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5744   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5745   newConn->alloc(getNodalConnectivityArrayLen()+21*nbOfCutCells,1);
5746   int *pt=newConn->getPointer();
5747   int *ptI=newConnI->getPointer();
5748   ptI[0]=0;
5749   const int *oldc=_nodal_connec->getConstPointer();
5750   const int *ci=_nodal_connec_index->getConstPointer();
5751   for(int i=0;i<nbOfCells;i++,ci++)
5752     {
5753       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5754         {
5755           for(int j=0;j<6;j++,pt+=5,ptI++)
5756             {
5757               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5758               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];
5759               *retPt++=i;
5760               ptI[1]=ptI[0]+5;
5761             }
5762         }
5763       else
5764         {
5765           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5766           ptI[1]=ptI[0]+ci[1]-ci[0];
5767           ptI++;
5768           *retPt++=i;
5769         }
5770     }
5771   _nodal_connec->decrRef();
5772   _nodal_connec=newConn.retn();
5773   _nodal_connec_index->decrRef();
5774   _nodal_connec_index=newConnI.retn();
5775   computeTypes();
5776   updateTime();
5777   return ret.retn();
5778 }
5779
5780 /*!
5781  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5782  * so that the number of cells remains the same. Quadratic faces are converted to
5783  * polygons. This method works only for 2D meshes in
5784  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5785  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5786  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5787  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5788  *         a polylinized edge constituting the input polygon.
5789  *  \throw If the coordinates array is not set.
5790  *  \throw If the nodal connectivity of cells is not defined.
5791  *  \throw If \a this->getMeshDimension() != 2.
5792  *  \throw If \a this->getSpaceDimension() != 2.
5793  */
5794 void MEDCouplingUMesh::tessellate2DInternal(double eps)
5795 {
5796   checkFullyDefined();
5797   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5798     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5799   double epsa=fabs(eps);
5800   if(epsa<std::numeric_limits<double>::min())
5801     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5802   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
5803   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
5804   revDesc1=0; revDescIndx1=0;
5805   mDesc->tessellate2D(eps);
5806   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5807   setCoords(mDesc->getCoords());
5808 }
5809
5810 /*!
5811  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5812  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5813  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5814  *         a sub-divided edge.
5815  *  \throw If the coordinates array is not set.
5816  *  \throw If the nodal connectivity of cells is not defined.
5817  *  \throw If \a this->getMeshDimension() != 1.
5818  *  \throw If \a this->getSpaceDimension() != 2.
5819  */
5820 void MEDCouplingUMesh::tessellate2DCurveInternal(double eps)
5821 {
5822   checkFullyDefined();
5823   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5824     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5825   double epsa=fabs(eps);
5826   if(epsa<std::numeric_limits<double>::min())
5827     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5828   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5829   int nbCells=getNumberOfCells();
5830   int nbNodes=getNumberOfNodes();
5831   const int *conn=_nodal_connec->getConstPointer();
5832   const int *connI=_nodal_connec_index->getConstPointer();
5833   const double *coords=_coords->getConstPointer();
5834   std::vector<double> addCoo;
5835   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5836   MCAuto<DataArrayInt> newConnI(DataArrayInt::New());
5837   newConnI->alloc(nbCells+1,1);
5838   int *newConnIPtr=newConnI->getPointer();
5839   *newConnIPtr=0;
5840   int tmp1[3];
5841   INTERP_KERNEL::Node *tmp2[3];
5842   std::set<INTERP_KERNEL::NormalizedCellType> types;
5843   for(int i=0;i<nbCells;i++,newConnIPtr++)
5844     {
5845       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5846       if(cm.isQuadratic())
5847         {//assert(connI[i+1]-connI[i]-1==3)
5848           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5849           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5850           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5851           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5852           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5853           if(eac)
5854             {
5855               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5856               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5857               delete eac;
5858               newConnIPtr[1]=(int)newConn.size();
5859             }
5860           else
5861             {
5862               types.insert(INTERP_KERNEL::NORM_SEG2);
5863               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5864               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5865               newConnIPtr[1]=newConnIPtr[0]+3;
5866             }
5867         }
5868       else
5869         {
5870           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5871           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5872           newConnIPtr[1]=newConnIPtr[0]+3;
5873         }
5874     }
5875   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5876     return ;
5877   _types=types;
5878   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5879   MCAuto<DataArrayInt> newConnArr=DataArrayInt::New();
5880   newConnArr->alloc((int)newConn.size(),1);
5881   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5882   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5883   MCAuto<DataArrayDouble> newCoords=DataArrayDouble::New();
5884   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5885   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5886   std::copy(addCoo.begin(),addCoo.end(),work);
5887   DataArrayDouble::SetArrayIn(newCoords,_coords);
5888   updateTime();
5889 }
5890
5891 /*!
5892  * 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.
5893  * This method completly ignore coordinates.
5894  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5895  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5896  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5897  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5898  */
5899 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5900 {
5901   checkFullyDefined();
5902   if(getMeshDimension()!=2)
5903     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5904   int nbOfCells=getNumberOfCells();
5905   int *connI=_nodal_connec_index->getPointer();
5906   int newConnLgth=0;
5907   for(int i=0;i<nbOfCells;i++,connI++)
5908     {
5909       int offset=descIndex[i];
5910       int nbOfEdges=descIndex[i+1]-offset;
5911       //
5912       bool ddirect=desc[offset+nbOfEdges-1]>0;
5913       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5914       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5915       for(int j=0;j<nbOfEdges;j++)
5916         {
5917           bool direct=desc[offset+j]>0;
5918           int edgeId=std::abs(desc[offset+j])-1;
5919           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5920             {
5921               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5922               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5923               int ref2=direct?id1:id2;
5924               if(ref==ref2)
5925                 {
5926                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5927                   newConnLgth+=nbOfSubNodes-1;
5928                   ref=direct?id2:id1;
5929                 }
5930               else
5931                 {
5932                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5933                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5934                 }
5935             }
5936           else
5937             {
5938               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5939             }
5940         }
5941       newConnLgth++;//+1 is for cell type
5942       connI[1]=newConnLgth;
5943     }
5944   //
5945   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5946   newConn->alloc(newConnLgth,1);
5947   int *work=newConn->getPointer();
5948   for(int i=0;i<nbOfCells;i++)
5949     {
5950       *work++=INTERP_KERNEL::NORM_POLYGON;
5951       int offset=descIndex[i];
5952       int nbOfEdges=descIndex[i+1]-offset;
5953       for(int j=0;j<nbOfEdges;j++)
5954         {
5955           bool direct=desc[offset+j]>0;
5956           int edgeId=std::abs(desc[offset+j])-1;
5957           if(direct)
5958             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5959           else
5960             {
5961               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5962               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5963               work=std::copy(it,it+nbOfSubNodes-1,work);
5964             }
5965         }
5966     }
5967   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5968   _types.clear();
5969   if(nbOfCells>0)
5970     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5971 }
5972
5973 /*!
5974  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5975  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5976  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5977  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5978  * so it can be useful to call mergeNodes() before calling this method.
5979  *  \throw If \a this->getMeshDimension() <= 1.
5980  *  \throw If the coordinates array is not set.
5981  *  \throw If the nodal connectivity of cells is not defined.
5982  */
5983 void MEDCouplingUMesh::convertDegeneratedCells()
5984 {
5985   checkFullyDefined();
5986   if(getMeshDimension()<=1)
5987     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5988   int nbOfCells=getNumberOfCells();
5989   if(nbOfCells<1)
5990     return ;
5991   int initMeshLgth=getNodalConnectivityArrayLen();
5992   int *conn=_nodal_connec->getPointer();
5993   int *index=_nodal_connec_index->getPointer();
5994   int posOfCurCell=0;
5995   int newPos=0;
5996   int lgthOfCurCell;
5997   for(int i=0;i<nbOfCells;i++)
5998     {
5999       lgthOfCurCell=index[i+1]-posOfCurCell;
6000       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
6001       int newLgth;
6002       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
6003                                                                                                      conn+newPos+1,newLgth);
6004       conn[newPos]=newType;
6005       newPos+=newLgth+1;
6006       posOfCurCell=index[i+1];
6007       index[i+1]=newPos;
6008     }
6009   if(newPos!=initMeshLgth)
6010     _nodal_connec->reAlloc(newPos);
6011   computeTypes();
6012 }
6013
6014 /*!
6015  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
6016  * A cell is considered to be oriented correctly if an angle between its
6017  * normal vector and a given vector is less than \c PI / \c 2.
6018  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6019  *         cells. 
6020  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6021  *         checked.
6022  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6023  *         is not cleared before filling in.
6024  *  \throw If \a this->getMeshDimension() != 2.
6025  *  \throw If \a this->getSpaceDimension() != 3.
6026  *
6027  *  \if ENABLE_EXAMPLES
6028  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6029  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6030  *  \endif
6031  */
6032 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6033 {
6034   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6035     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6036   int nbOfCells=getNumberOfCells();
6037   const int *conn=_nodal_connec->getConstPointer();
6038   const int *connI=_nodal_connec_index->getConstPointer();
6039   const double *coordsPtr=_coords->getConstPointer();
6040   for(int i=0;i<nbOfCells;i++)
6041     {
6042       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6043       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6044         {
6045           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6046           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6047             cells.push_back(i);
6048         }
6049     }
6050 }
6051
6052 /*!
6053  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6054  * considered to be oriented correctly if an angle between its normal vector and a
6055  * given vector is less than \c PI / \c 2. 
6056  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6057  *         cells. 
6058  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6059  *         checked.
6060  *  \throw If \a this->getMeshDimension() != 2.
6061  *  \throw If \a this->getSpaceDimension() != 3.
6062  *
6063  *  \if ENABLE_EXAMPLES
6064  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6065  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6066  *  \endif
6067  *
6068  *  \sa changeOrientationOfCells
6069  */
6070 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6071 {
6072   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6073     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6074   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6075   const int *connI(_nodal_connec_index->getConstPointer());
6076   const double *coordsPtr(_coords->getConstPointer());
6077   bool isModified(false);
6078   for(int i=0;i<nbOfCells;i++)
6079     {
6080       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6081       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6082         {
6083           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6084           bool isQuadratic(cm.isQuadratic());
6085           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6086             {
6087               isModified=true;
6088               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6089             }
6090         }
6091     }
6092   if(isModified)
6093     _nodal_connec->declareAsNew();
6094   updateTime();
6095 }
6096
6097 /*!
6098  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6099  *
6100  * \sa orientCorrectly2DCells
6101  */
6102 void MEDCouplingUMesh::changeOrientationOfCells()
6103 {
6104   int mdim(getMeshDimension());
6105   if(mdim!=2 && mdim!=1)
6106     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6107   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6108   const int *connI(_nodal_connec_index->getConstPointer());
6109   if(mdim==2)
6110     {//2D
6111       for(int i=0;i<nbOfCells;i++)
6112         {
6113           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6114           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6115           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6116         }
6117     }
6118   else
6119     {//1D
6120       for(int i=0;i<nbOfCells;i++)
6121         {
6122           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6123           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6124           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6125         }
6126     }
6127 }
6128
6129 /*!
6130  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6131  * oriented facets. The normal vector of the facet should point out of the cell.
6132  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6133  *         is not cleared before filling in.
6134  *  \throw If \a this->getMeshDimension() != 3.
6135  *  \throw If \a this->getSpaceDimension() != 3.
6136  *  \throw If the coordinates array is not set.
6137  *  \throw If the nodal connectivity of cells is not defined.
6138  *
6139  *  \if ENABLE_EXAMPLES
6140  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6141  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6142  *  \endif
6143  */
6144 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6145 {
6146   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6147     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6148   int nbOfCells=getNumberOfCells();
6149   const int *conn=_nodal_connec->getConstPointer();
6150   const int *connI=_nodal_connec_index->getConstPointer();
6151   const double *coordsPtr=_coords->getConstPointer();
6152   for(int i=0;i<nbOfCells;i++)
6153     {
6154       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6155       if(type==INTERP_KERNEL::NORM_POLYHED)
6156         {
6157           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6158             cells.push_back(i);
6159         }
6160     }
6161 }
6162
6163 /*!
6164  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6165  * out of the cell. 
6166  *  \throw If \a this->getMeshDimension() != 3.
6167  *  \throw If \a this->getSpaceDimension() != 3.
6168  *  \throw If the coordinates array is not set.
6169  *  \throw If the nodal connectivity of cells is not defined.
6170  *  \throw If the reparation fails.
6171  *
6172  *  \if ENABLE_EXAMPLES
6173  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6174  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6175  *  \endif
6176  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6177  */
6178 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6179 {
6180   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6181     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6182   int nbOfCells=getNumberOfCells();
6183   int *conn=_nodal_connec->getPointer();
6184   const int *connI=_nodal_connec_index->getConstPointer();
6185   const double *coordsPtr=_coords->getConstPointer();
6186   for(int i=0;i<nbOfCells;i++)
6187     {
6188       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6189       if(type==INTERP_KERNEL::NORM_POLYHED)
6190         {
6191           try
6192           {
6193               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6194                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6195           }
6196           catch(INTERP_KERNEL::Exception& e)
6197           {
6198               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6199               throw INTERP_KERNEL::Exception(oss.str().c_str());
6200           }
6201         }
6202     }
6203   updateTime();
6204 }
6205
6206 /*!
6207  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6208  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6209  * according to which the first facet of the cell should be oriented to have the normal vector
6210  * pointing out of cell.
6211  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6212  *         cells. The caller is to delete this array using decrRef() as it is no more
6213  *         needed. 
6214  *  \throw If \a this->getMeshDimension() != 3.
6215  *  \throw If \a this->getSpaceDimension() != 3.
6216  *  \throw If the coordinates array is not set.
6217  *  \throw If the nodal connectivity of cells is not defined.
6218  *
6219  *  \if ENABLE_EXAMPLES
6220  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6221  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6222  *  \endif
6223  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6224  */
6225 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6226 {
6227   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6228   if(getMeshDimension()!=3)
6229     throw INTERP_KERNEL::Exception(msg);
6230   int spaceDim=getSpaceDimension();
6231   if(spaceDim!=3)
6232     throw INTERP_KERNEL::Exception(msg);
6233   //
6234   int nbOfCells=getNumberOfCells();
6235   int *conn=_nodal_connec->getPointer();
6236   const int *connI=_nodal_connec_index->getConstPointer();
6237   const double *coo=getCoords()->getConstPointer();
6238   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6239   for(int i=0;i<nbOfCells;i++)
6240     {
6241       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6242       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6243         {
6244           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6245             {
6246               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6247               cells->pushBackSilent(i);
6248             }
6249         }
6250     }
6251   return cells.retn();
6252 }
6253
6254 /*!
6255  * This method is a faster method to correct orientation of all 3D cells in \a this.
6256  * 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.
6257  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
6258  * 
6259  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6260  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6261  */
6262 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6263 {
6264   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6265     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6266   int nbOfCells=getNumberOfCells();
6267   int *conn=_nodal_connec->getPointer();
6268   const int *connI=_nodal_connec_index->getConstPointer();
6269   const double *coordsPtr=_coords->getConstPointer();
6270   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6271   for(int i=0;i<nbOfCells;i++)
6272     {
6273       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6274       switch(type)
6275       {
6276         case INTERP_KERNEL::NORM_TETRA4:
6277           {
6278             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6279               {
6280                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6281                 ret->pushBackSilent(i);
6282               }
6283             break;
6284           }
6285         case INTERP_KERNEL::NORM_PYRA5:
6286           {
6287             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6288               {
6289                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6290                 ret->pushBackSilent(i);
6291               }
6292             break;
6293           }
6294         case INTERP_KERNEL::NORM_PENTA6:
6295         case INTERP_KERNEL::NORM_HEXA8:
6296         case INTERP_KERNEL::NORM_HEXGP12:
6297           {
6298             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6299               {
6300                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6301                 ret->pushBackSilent(i);
6302               }
6303             break;
6304           }
6305         case INTERP_KERNEL::NORM_POLYHED:
6306           {
6307             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6308               {
6309                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6310                 ret->pushBackSilent(i);
6311               }
6312             break;
6313           }
6314         default:
6315           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 !");
6316       }
6317     }
6318   updateTime();
6319   return ret.retn();
6320 }
6321
6322 /*!
6323  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6324  * If it is not the case an exception will be thrown.
6325  * This method is fast because the first cell of \a this is used to compute the plane.
6326  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6327  * \param pos output of size at least 3 used to store a point owned of searched plane.
6328  */
6329 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6330 {
6331   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6332     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6333   const int *conn=_nodal_connec->getConstPointer();
6334   const int *connI=_nodal_connec_index->getConstPointer();
6335   const double *coordsPtr=_coords->getConstPointer();
6336   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6337   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6338 }
6339
6340 /*!
6341  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6342  * cells. Currently cells of the following types are treated:
6343  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6344  * For a cell of other type an exception is thrown.
6345  * Space dimension of a 2D mesh can be either 2 or 3.
6346  * The Edge Ratio of a cell \f$t\f$ is: 
6347  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6348  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6349  *  the smallest edge lengths of \f$t\f$.
6350  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6351  *          cells and one time, lying on \a this mesh. The caller is to delete this
6352  *          field using decrRef() as it is no more needed. 
6353  *  \throw If the coordinates array is not set.
6354  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6355  *  \throw If the connectivity data array has more than one component.
6356  *  \throw If the connectivity data array has a named component.
6357  *  \throw If the connectivity index data array has more than one component.
6358  *  \throw If the connectivity index data array has a named component.
6359  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6360  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6361  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6362  */
6363 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6364 {
6365   checkConsistencyLight();
6366   int spaceDim=getSpaceDimension();
6367   int meshDim=getMeshDimension();
6368   if(spaceDim!=2 && spaceDim!=3)
6369     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6370   if(meshDim!=2 && meshDim!=3)
6371     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6372   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6373   ret->setMesh(this);
6374   int nbOfCells=getNumberOfCells();
6375   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6376   arr->alloc(nbOfCells,1);
6377   double *pt=arr->getPointer();
6378   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6379   const int *conn=_nodal_connec->getConstPointer();
6380   const int *connI=_nodal_connec_index->getConstPointer();
6381   const double *coo=_coords->getConstPointer();
6382   double tmp[12];
6383   for(int i=0;i<nbOfCells;i++,pt++)
6384     {
6385       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6386       switch(t)
6387       {
6388         case INTERP_KERNEL::NORM_TRI3:
6389           {
6390             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6391             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6392             break;
6393           }
6394         case INTERP_KERNEL::NORM_QUAD4:
6395           {
6396             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6397             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6398             break;
6399           }
6400         case INTERP_KERNEL::NORM_TETRA4:
6401           {
6402             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6403             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6404             break;
6405           }
6406         default:
6407           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6408       }
6409       conn+=connI[i+1]-connI[i];
6410     }
6411   ret->setName("EdgeRatio");
6412   ret->synchronizeTimeWithSupport();
6413   return ret.retn();
6414 }
6415
6416 /*!
6417  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6418  * cells. Currently cells of the following types are treated:
6419  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6420  * For a cell of other type an exception is thrown.
6421  * Space dimension of a 2D mesh can be either 2 or 3.
6422  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6423  *          cells and one time, lying on \a this mesh. The caller is to delete this
6424  *          field using decrRef() as it is no more needed. 
6425  *  \throw If the coordinates array is not set.
6426  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6427  *  \throw If the connectivity data array has more than one component.
6428  *  \throw If the connectivity data array has a named component.
6429  *  \throw If the connectivity index data array has more than one component.
6430  *  \throw If the connectivity index data array has a named component.
6431  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6432  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6433  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6434  */
6435 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6436 {
6437   checkConsistencyLight();
6438   int spaceDim=getSpaceDimension();
6439   int meshDim=getMeshDimension();
6440   if(spaceDim!=2 && spaceDim!=3)
6441     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6442   if(meshDim!=2 && meshDim!=3)
6443     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6444   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6445   ret->setMesh(this);
6446   int nbOfCells=getNumberOfCells();
6447   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6448   arr->alloc(nbOfCells,1);
6449   double *pt=arr->getPointer();
6450   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6451   const int *conn=_nodal_connec->getConstPointer();
6452   const int *connI=_nodal_connec_index->getConstPointer();
6453   const double *coo=_coords->getConstPointer();
6454   double tmp[12];
6455   for(int i=0;i<nbOfCells;i++,pt++)
6456     {
6457       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6458       switch(t)
6459       {
6460         case INTERP_KERNEL::NORM_TRI3:
6461           {
6462             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6463             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6464             break;
6465           }
6466         case INTERP_KERNEL::NORM_QUAD4:
6467           {
6468             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6469             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6470             break;
6471           }
6472         case INTERP_KERNEL::NORM_TETRA4:
6473           {
6474             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6475             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6476             break;
6477           }
6478         default:
6479           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6480       }
6481       conn+=connI[i+1]-connI[i];
6482     }
6483   ret->setName("AspectRatio");
6484   ret->synchronizeTimeWithSupport();
6485   return ret.retn();
6486 }
6487
6488 /*!
6489  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6490  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6491  * treated: INTERP_KERNEL::NORM_QUAD4.
6492  * For a cell of other type an exception is thrown.
6493  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6494  *          cells and one time, lying on \a this mesh. The caller is to delete this
6495  *          field using decrRef() as it is no more needed. 
6496  *  \throw If the coordinates array is not set.
6497  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6498  *  \throw If the connectivity data array has more than one component.
6499  *  \throw If the connectivity data array has a named component.
6500  *  \throw If the connectivity index data array has more than one component.
6501  *  \throw If the connectivity index data array has a named component.
6502  *  \throw If \a this->getMeshDimension() != 2.
6503  *  \throw If \a this->getSpaceDimension() != 3.
6504  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6505  */
6506 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6507 {
6508   checkConsistencyLight();
6509   int spaceDim=getSpaceDimension();
6510   int meshDim=getMeshDimension();
6511   if(spaceDim!=3)
6512     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6513   if(meshDim!=2)
6514     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6515   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6516   ret->setMesh(this);
6517   int nbOfCells=getNumberOfCells();
6518   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6519   arr->alloc(nbOfCells,1);
6520   double *pt=arr->getPointer();
6521   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6522   const int *conn=_nodal_connec->getConstPointer();
6523   const int *connI=_nodal_connec_index->getConstPointer();
6524   const double *coo=_coords->getConstPointer();
6525   double tmp[12];
6526   for(int i=0;i<nbOfCells;i++,pt++)
6527     {
6528       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6529       switch(t)
6530       {
6531         case INTERP_KERNEL::NORM_QUAD4:
6532           {
6533             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6534             *pt=INTERP_KERNEL::quadWarp(tmp);
6535             break;
6536           }
6537         default:
6538           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6539       }
6540       conn+=connI[i+1]-connI[i];
6541     }
6542   ret->setName("Warp");
6543   ret->synchronizeTimeWithSupport();
6544   return ret.retn();
6545 }
6546
6547
6548 /*!
6549  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6550  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6551  * treated: INTERP_KERNEL::NORM_QUAD4.
6552  * For a cell of other type an exception is thrown.
6553  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6554  *          cells and one time, lying on \a this mesh. The caller is to delete this
6555  *          field using decrRef() as it is no more needed. 
6556  *  \throw If the coordinates array is not set.
6557  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6558  *  \throw If the connectivity data array has more than one component.
6559  *  \throw If the connectivity data array has a named component.
6560  *  \throw If the connectivity index data array has more than one component.
6561  *  \throw If the connectivity index data array has a named component.
6562  *  \throw If \a this->getMeshDimension() != 2.
6563  *  \throw If \a this->getSpaceDimension() != 3.
6564  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6565  */
6566 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6567 {
6568   checkConsistencyLight();
6569   int spaceDim=getSpaceDimension();
6570   int meshDim=getMeshDimension();
6571   if(spaceDim!=3)
6572     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6573   if(meshDim!=2)
6574     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6575   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6576   ret->setMesh(this);
6577   int nbOfCells=getNumberOfCells();
6578   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6579   arr->alloc(nbOfCells,1);
6580   double *pt=arr->getPointer();
6581   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6582   const int *conn=_nodal_connec->getConstPointer();
6583   const int *connI=_nodal_connec_index->getConstPointer();
6584   const double *coo=_coords->getConstPointer();
6585   double tmp[12];
6586   for(int i=0;i<nbOfCells;i++,pt++)
6587     {
6588       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6589       switch(t)
6590       {
6591         case INTERP_KERNEL::NORM_QUAD4:
6592           {
6593             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6594             *pt=INTERP_KERNEL::quadSkew(tmp);
6595             break;
6596           }
6597         default:
6598           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6599       }
6600       conn+=connI[i+1]-connI[i];
6601     }
6602   ret->setName("Skew");
6603   ret->synchronizeTimeWithSupport();
6604   return ret.retn();
6605 }
6606
6607 /*!
6608  * Returns the cell field giving for each cell in \a this its diameter. Diameter means the max length of all possible SEG2 in the cell.
6609  *
6610  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6611  *
6612  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6613  */
6614 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6615 {
6616   checkConsistencyLight();
6617   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6618   ret->setMesh(this);
6619   std::set<INTERP_KERNEL::NormalizedCellType> types;
6620   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6621   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6622   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6623   arr->alloc(nbCells,1);
6624   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6625     {
6626       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6627       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
6628       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6629     }
6630   ret->setArray(arr);
6631   ret->setName("Diameter");
6632   return ret.retn();
6633 }
6634
6635 /*!
6636  * This method aggregate the bbox of each cell and put it into bbox parameter.
6637  * 
6638  * \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)
6639  *                         For all other cases this input parameter is ignored.
6640  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6641  * 
6642  * \throw If \a this is not fully set (coordinates and connectivity).
6643  * \throw If a cell in \a this has no valid nodeId.
6644  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6645  */
6646 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6647 {
6648   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6649   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.
6650     return getBoundingBoxForBBTreeFast();
6651   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6652     {
6653       bool presenceOfQuadratic(false);
6654       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6655         {
6656           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6657           if(cm.isQuadratic())
6658             presenceOfQuadratic=true;
6659         }
6660       if(!presenceOfQuadratic)
6661         return getBoundingBoxForBBTreeFast();
6662       if(mDim==2 && sDim==2)
6663         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6664       else
6665         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6666     }
6667   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) !");
6668 }
6669
6670 /*!
6671  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6672  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6673  * 
6674  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6675  * 
6676  * \throw If \a this is not fully set (coordinates and connectivity).
6677  * \throw If a cell in \a this has no valid nodeId.
6678  */
6679 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6680 {
6681   checkFullyDefined();
6682   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6683   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6684   double *bbox(ret->getPointer());
6685   for(int i=0;i<nbOfCells*spaceDim;i++)
6686     {
6687       bbox[2*i]=std::numeric_limits<double>::max();
6688       bbox[2*i+1]=-std::numeric_limits<double>::max();
6689     }
6690   const double *coordsPtr(_coords->getConstPointer());
6691   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6692   for(int i=0;i<nbOfCells;i++)
6693     {
6694       int offset=connI[i]+1;
6695       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6696       for(int j=0;j<nbOfNodesForCell;j++)
6697         {
6698           int nodeId=conn[offset+j];
6699           if(nodeId>=0 && nodeId<nbOfNodes)
6700             {
6701               for(int k=0;k<spaceDim;k++)
6702                 {
6703                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6704                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6705                 }
6706               kk++;
6707             }
6708         }
6709       if(kk==0)
6710         {
6711           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6712           throw INTERP_KERNEL::Exception(oss.str().c_str());
6713         }
6714     }
6715   return ret.retn();
6716 }
6717
6718 /*!
6719  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6720  * useful for 2D meshes having quadratic cells
6721  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6722  * the two extremities of the arc of circle).
6723  * 
6724  * \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)
6725  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6726  * \throw If \a this is not fully defined.
6727  * \throw If \a this is not a mesh with meshDimension equal to 2.
6728  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6729  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6730  */
6731 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6732 {
6733   checkFullyDefined();
6734   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6735   if(spaceDim!=2 || mDim!=2)
6736     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!");
6737   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6738   double *bbox(ret->getPointer());
6739   const double *coords(_coords->getConstPointer());
6740   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6741   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6742     {
6743       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6744       int sz(connI[1]-connI[0]-1);
6745       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6746       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6747       INTERP_KERNEL::QuadraticPolygon *pol(0);
6748       for(int j=0;j<sz;j++)
6749         {
6750           int nodeId(conn[*connI+1+j]);
6751           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6752         }
6753       if(!cm.isQuadratic())
6754         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6755       else
6756         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6757       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6758       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6759     }
6760   return ret.retn();
6761 }
6762
6763 /*!
6764  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6765  * useful for 2D meshes having quadratic cells
6766  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6767  * the two extremities of the arc of circle).
6768  * 
6769  * \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)
6770  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6771  * \throw If \a this is not fully defined.
6772  * \throw If \a this is not a mesh with meshDimension equal to 1.
6773  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6774  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6775  */
6776 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6777 {
6778   checkFullyDefined();
6779   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6780   if(spaceDim!=2 || mDim!=1)
6781     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!");
6782   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6783   double *bbox(ret->getPointer());
6784   const double *coords(_coords->getConstPointer());
6785   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6786   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6787     {
6788       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6789       int sz(connI[1]-connI[0]-1);
6790       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6791       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6792       INTERP_KERNEL::Edge *edge(0);
6793       for(int j=0;j<sz;j++)
6794         {
6795           int nodeId(conn[*connI+1+j]);
6796           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6797         }
6798       if(!cm.isQuadratic())
6799         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6800       else
6801         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6802       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6803       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6804     }
6805   return ret.retn();
6806 }
6807
6808 /// @cond INTERNAL
6809
6810 namespace MEDCouplingImpl
6811 {
6812   class ConnReader
6813   {
6814   public:
6815     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6816     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6817   private:
6818     const int *_conn;
6819     int _val;
6820   };
6821
6822   class ConnReader2
6823   {
6824   public:
6825     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6826     bool operator() (const int& pos) { return _conn[pos]==_val; }
6827   private:
6828     const int *_conn;
6829     int _val;
6830   };
6831 }
6832
6833 /// @endcond
6834
6835 /*!
6836  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6837  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6838  * \a this is composed in cell types.
6839  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6840  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6841  * This parameter is kept only for compatibility with other methode listed above.
6842  */
6843 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6844 {
6845   checkConnectivityFullyDefined();
6846   const int *conn=_nodal_connec->getConstPointer();
6847   const int *connI=_nodal_connec_index->getConstPointer();
6848   const int *work=connI;
6849   int nbOfCells=getNumberOfCells();
6850   std::size_t n=getAllGeoTypes().size();
6851   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6852   std::set<INTERP_KERNEL::NormalizedCellType> types;
6853   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6854     {
6855       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6856       if(types.find(typ)!=types.end())
6857         {
6858           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6859           oss << " is not contiguous !";
6860           throw INTERP_KERNEL::Exception(oss.str().c_str());
6861         }
6862       types.insert(typ);
6863       ret[3*i]=typ;
6864       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
6865       ret[3*i+1]=(int)std::distance(work,work2);
6866       work=work2;
6867     }
6868   return ret;
6869 }
6870
6871 /*!
6872  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6873  * only for types cell, type node is not managed.
6874  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6875  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6876  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6877  * If 2 or more same geometric type is in \a code and exception is thrown too.
6878  *
6879  * This method firstly checks
6880  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6881  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6882  * an exception is thrown too.
6883  * 
6884  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6885  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6886  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6887  */
6888 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6889 {
6890   if(code.empty())
6891     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6892   std::size_t sz=code.size();
6893   std::size_t n=sz/3;
6894   if(sz%3!=0)
6895     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6896   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6897   int nb=0;
6898   bool isNoPflUsed=true;
6899   for(std::size_t i=0;i<n;i++)
6900     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6901       {
6902         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6903         nb+=code[3*i+1];
6904         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6905           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6906         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6907       }
6908   if(types.size()!=n)
6909     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6910   if(isNoPflUsed)
6911     {
6912       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6913         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6914       if(types.size()==_types.size())
6915         return 0;
6916     }
6917   MCAuto<DataArrayInt> ret=DataArrayInt::New();
6918   ret->alloc(nb,1);
6919   int *retPtr=ret->getPointer();
6920   const int *connI=_nodal_connec_index->getConstPointer();
6921   const int *conn=_nodal_connec->getConstPointer();
6922   int nbOfCells=getNumberOfCells();
6923   const int *i=connI;
6924   int kk=0;
6925   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6926     {
6927       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
6928       int offset=(int)std::distance(connI,i);
6929       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
6930       int nbOfCellsOfCurType=(int)std::distance(i,j);
6931       if(code[3*kk+2]==-1)
6932         for(int k=0;k<nbOfCellsOfCurType;k++)
6933           *retPtr++=k+offset;
6934       else
6935         {
6936           int idInIdsPerType=code[3*kk+2];
6937           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6938             {
6939               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6940               if(zePfl)
6941                 {
6942                   zePfl->checkAllocated();
6943                   if(zePfl->getNumberOfComponents()==1)
6944                     {
6945                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6946                         {
6947                           if(*k>=0 && *k<nbOfCellsOfCurType)
6948                             *retPtr=(*k)+offset;
6949                           else
6950                             {
6951                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6952                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6953                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6954                             }
6955                         }
6956                     }
6957                   else
6958                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6959                 }
6960               else
6961                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6962             }
6963           else
6964             {
6965               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6966               oss << " should be in [0," << idsPerType.size() << ") !";
6967               throw INTERP_KERNEL::Exception(oss.str().c_str());
6968             }
6969         }
6970       i=j;
6971     }
6972   return ret.retn();
6973 }
6974
6975 /*!
6976  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
6977  * 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.
6978  * 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.
6979  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6980  * 
6981  * \param [in] profile
6982  * \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.
6983  * \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,
6984  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6985  * \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.
6986  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6987  * \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
6988  */
6989 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6990 {
6991   if(!profile)
6992     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6993   if(profile->getNumberOfComponents()!=1)
6994     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6995   checkConnectivityFullyDefined();
6996   const int *conn=_nodal_connec->getConstPointer();
6997   const int *connI=_nodal_connec_index->getConstPointer();
6998   int nbOfCells=getNumberOfCells();
6999   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7000   std::vector<int> typeRangeVals(1);
7001   for(const int *i=connI;i!=connI+nbOfCells;)
7002     {
7003       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7004       if(std::find(types.begin(),types.end(),curType)!=types.end())
7005         {
7006           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
7007         }
7008       types.push_back(curType);
7009       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7010       typeRangeVals.push_back((int)std::distance(connI,i));
7011     }
7012   //
7013   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
7014   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
7015   MCAuto<DataArrayInt> tmp0=castArr;
7016   MCAuto<DataArrayInt> tmp1=rankInsideCast;
7017   MCAuto<DataArrayInt> tmp2=castsPresent;
7018   //
7019   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
7020   code.resize(3*nbOfCastsFinal);
7021   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
7022   std::vector< MCAuto<DataArrayInt> > idsPerType2;
7023   for(int i=0;i<nbOfCastsFinal;i++)
7024     {
7025       int castId=castsPresent->getIJ(i,0);
7026       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
7027       idsInPflPerType2.push_back(tmp3);
7028       code[3*i]=(int)types[castId];
7029       code[3*i+1]=tmp3->getNumberOfTuples();
7030       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7031       if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
7032         {
7033           tmp4->copyStringInfoFrom(*profile);
7034           idsPerType2.push_back(tmp4);
7035           code[3*i+2]=(int)idsPerType2.size()-1;
7036         }
7037       else
7038         {
7039           code[3*i+2]=-1;
7040         }
7041     }
7042   std::size_t sz2=idsInPflPerType2.size();
7043   idsInPflPerType.resize(sz2);
7044   for(std::size_t i=0;i<sz2;i++)
7045     {
7046       DataArrayInt *locDa=idsInPflPerType2[i];
7047       locDa->incrRef();
7048       idsInPflPerType[i]=locDa;
7049     }
7050   std::size_t sz=idsPerType2.size();
7051   idsPerType.resize(sz);
7052   for(std::size_t i=0;i<sz;i++)
7053     {
7054       DataArrayInt *locDa=idsPerType2[i];
7055       locDa->incrRef();
7056       idsPerType[i]=locDa;
7057     }
7058 }
7059
7060 /*!
7061  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7062  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7063  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7064  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as MEDCoupling::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.
7065  */
7066 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7067 {
7068   checkFullyDefined();
7069   nM1LevMesh->checkFullyDefined();
7070   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7071     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7072   if(_coords!=nM1LevMesh->getCoords())
7073     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7074   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
7075   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
7076   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7077   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7078   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7079   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7080   tmp->setConnectivity(tmp0,tmp1);
7081   tmp->renumberCells(ret0->getConstPointer(),false);
7082   revDesc=tmp->getNodalConnectivity();
7083   revDescIndx=tmp->getNodalConnectivityIndex();
7084   DataArrayInt *ret=0;
7085   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7086     {
7087       int tmp2;
7088       ret->getMaxValue(tmp2);
7089       ret->decrRef();
7090       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7091       throw INTERP_KERNEL::Exception(oss.str().c_str());
7092     }
7093   nM1LevMeshIds=ret;
7094   //
7095   revDesc->incrRef();
7096   revDescIndx->incrRef();
7097   ret1->incrRef();
7098   ret0->incrRef();
7099   meshnM1Old2New=ret0;
7100   return ret1;
7101 }
7102
7103 /*!
7104  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7105  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7106  * in "Old to New" mode.
7107  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7108  *          this array using decrRef() as it is no more needed.
7109  *  \throw If the nodal connectivity of cells is not defined.
7110  */
7111 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7112 {
7113   checkConnectivityFullyDefined();
7114   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7115   renumberCells(ret->getConstPointer(),false);
7116   return ret.retn();
7117 }
7118
7119 /*!
7120  * This methods checks that cells are sorted by their types.
7121  * This method makes asumption (no check) that connectivity is correctly set before calling.
7122  */
7123 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7124 {
7125   checkFullyDefined();
7126   const int *conn=_nodal_connec->getConstPointer();
7127   const int *connI=_nodal_connec_index->getConstPointer();
7128   int nbOfCells=getNumberOfCells();
7129   std::set<INTERP_KERNEL::NormalizedCellType> types;
7130   for(const int *i=connI;i!=connI+nbOfCells;)
7131     {
7132       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7133       if(types.find(curType)!=types.end())
7134         return false;
7135       types.insert(curType);
7136       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7137     }
7138   return true;
7139 }
7140
7141 /*!
7142  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7143  * The geometric type order is specified by MED file.
7144  * 
7145  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7146  */
7147 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7148 {
7149   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7150 }
7151
7152 /*!
7153  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7154  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7155  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7156  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7157  */
7158 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7159 {
7160   checkFullyDefined();
7161   const int *conn=_nodal_connec->getConstPointer();
7162   const int *connI=_nodal_connec_index->getConstPointer();
7163   int nbOfCells=getNumberOfCells();
7164   if(nbOfCells==0)
7165     return true;
7166   int lastPos=-1;
7167   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7168   for(const int *i=connI;i!=connI+nbOfCells;)
7169     {
7170       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7171       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7172       if(isTypeExists!=orderEnd)
7173         {
7174           int pos=(int)std::distance(orderBg,isTypeExists);
7175           if(pos<=lastPos)
7176             return false;
7177           lastPos=pos;
7178           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7179         }
7180       else
7181         {
7182           if(sg.find(curType)==sg.end())
7183             {
7184               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7185               sg.insert(curType);
7186             }
7187           else
7188             return false;
7189         }
7190     }
7191   return true;
7192 }
7193
7194 /*!
7195  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7196  * 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
7197  * 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'.
7198  */
7199 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7200 {
7201   checkConnectivityFullyDefined();
7202   int nbOfCells=getNumberOfCells();
7203   const int *conn=_nodal_connec->getConstPointer();
7204   const int *connI=_nodal_connec_index->getConstPointer();
7205   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
7206   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
7207   tmpa->alloc(nbOfCells,1);
7208   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7209   tmpb->fillWithZero();
7210   int *tmp=tmpa->getPointer();
7211   int *tmp2=tmpb->getPointer();
7212   for(const int *i=connI;i!=connI+nbOfCells;i++)
7213     {
7214       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7215       if(where!=orderEnd)
7216         {
7217           int pos=(int)std::distance(orderBg,where);
7218           tmp2[pos]++;
7219           tmp[std::distance(connI,i)]=pos;
7220         }
7221       else
7222         {
7223           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7224           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7225           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7226           throw INTERP_KERNEL::Exception(oss.str().c_str());
7227         }
7228     }
7229   nbPerType=tmpb.retn();
7230   return tmpa.retn();
7231 }
7232
7233 /*!
7234  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7235  *
7236  * \return a new object containing the old to new correspondance.
7237  *
7238  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7239  */
7240 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7241 {
7242   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7243 }
7244
7245 /*!
7246  * 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.
7247  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7248  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7249  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7250  */
7251 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7252 {
7253   DataArrayInt *nbPerType=0;
7254   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7255   nbPerType->decrRef();
7256   return tmpa->buildPermArrPerLevel();
7257 }
7258
7259 /*!
7260  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7261  * The number of cells remains unchanged after the call of this method.
7262  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7263  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7264  *
7265  * \return the array giving the correspondance old to new.
7266  */
7267 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7268 {
7269   checkFullyDefined();
7270   computeTypes();
7271   const int *conn=_nodal_connec->getConstPointer();
7272   const int *connI=_nodal_connec_index->getConstPointer();
7273   int nbOfCells=getNumberOfCells();
7274   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7275   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7276     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7277       {
7278         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7279         types.push_back(curType);
7280         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7281       }
7282   DataArrayInt *ret=DataArrayInt::New();
7283   ret->alloc(nbOfCells,1);
7284   int *retPtr=ret->getPointer();
7285   std::fill(retPtr,retPtr+nbOfCells,-1);
7286   int newCellId=0;
7287   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7288     {
7289       for(const int *i=connI;i!=connI+nbOfCells;i++)
7290         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7291           retPtr[std::distance(connI,i)]=newCellId++;
7292     }
7293   renumberCells(retPtr,false);
7294   return ret;
7295 }
7296
7297 /*!
7298  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7299  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7300  * This method makes asumption that connectivity is correctly set before calling.
7301  */
7302 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7303 {
7304   checkConnectivityFullyDefined();
7305   const int *conn=_nodal_connec->getConstPointer();
7306   const int *connI=_nodal_connec_index->getConstPointer();
7307   int nbOfCells=getNumberOfCells();
7308   std::vector<MEDCouplingUMesh *> ret;
7309   for(const int *i=connI;i!=connI+nbOfCells;)
7310     {
7311       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7312       int beginCellId=(int)std::distance(connI,i);
7313       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7314       int endCellId=(int)std::distance(connI,i);
7315       int sz=endCellId-beginCellId;
7316       int *cells=new int[sz];
7317       for(int j=0;j<sz;j++)
7318         cells[j]=beginCellId+j;
7319       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7320       delete [] cells;
7321       ret.push_back(m);
7322     }
7323   return ret;
7324 }
7325
7326 /*!
7327  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7328  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7329  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7330  *
7331  * \return a newly allocated instance, that the caller must manage.
7332  * \throw If \a this contains more than one geometric type.
7333  * \throw If the nodal connectivity of \a this is not fully defined.
7334  * \throw If the internal data is not coherent.
7335  */
7336 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7337 {
7338   checkConnectivityFullyDefined();
7339   if(_types.size()!=1)
7340     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7341   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7342   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7343   ret->setCoords(getCoords());
7344   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7345   if(retC)
7346     {
7347       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7348       retC->setNodalConnectivity(c);
7349     }
7350   else
7351     {
7352       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7353       if(!retD)
7354         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7355       DataArrayInt *c=0,*ci=0;
7356       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7357       MCAuto<DataArrayInt> cs(c),cis(ci);
7358       retD->setNodalConnectivity(cs,cis);
7359     }
7360   return ret.retn();
7361 }
7362
7363 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7364 {
7365   checkConnectivityFullyDefined();
7366   if(_types.size()!=1)
7367     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7368   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7369   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7370   if(cm.isDynamic())
7371     {
7372       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7373       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7374       throw INTERP_KERNEL::Exception(oss.str().c_str());
7375     }
7376   int nbCells=getNumberOfCells();
7377   int typi=(int)typ;
7378   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7379   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7380   int *outPtr=connOut->getPointer();
7381   const int *conn=_nodal_connec->begin();
7382   const int *connI=_nodal_connec_index->begin();
7383   nbNodesPerCell++;
7384   for(int i=0;i<nbCells;i++,connI++)
7385     {
7386       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7387         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7388       else
7389         {
7390           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 << ") !";
7391           throw INTERP_KERNEL::Exception(oss.str().c_str());
7392         }
7393     }
7394   return connOut.retn();
7395 }
7396
7397 /*!
7398  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7399  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7400  * \param nodalConn
7401  * \param nodalConnI
7402  */
7403 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7404 {
7405   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
7406   checkConnectivityFullyDefined();
7407   if(_types.size()!=1)
7408     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7409   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7410   if(lgth<nbCells)
7411     throw INTERP_KERNEL::Exception(msg0);
7412   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7413   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7414   int *cp(c->getPointer()),*cip(ci->getPointer());
7415   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7416   cip[0]=0;
7417   for(int i=0;i<nbCells;i++,cip++,incip++)
7418     {
7419       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7420       int delta(stop-strt);
7421       if(delta>=1)
7422         {
7423           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7424             cp=std::copy(incp+strt,incp+stop,cp);
7425           else
7426             throw INTERP_KERNEL::Exception(msg0);
7427         }
7428       else
7429         throw INTERP_KERNEL::Exception(msg0);
7430       cip[1]=cip[0]+delta;
7431     }
7432   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7433 }
7434
7435 /*!
7436  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7437  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7438  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7439  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7440  * are not used here to avoid the build of big permutation array.
7441  *
7442  * \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
7443  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7444  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7445  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7446  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7447  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7448  * \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
7449  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7450  */
7451 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7452                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7453                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7454 {
7455   std::vector<const MEDCouplingUMesh *> ms2;
7456   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7457     if(*it)
7458       {
7459         (*it)->checkConnectivityFullyDefined();
7460         ms2.push_back(*it);
7461       }
7462   if(ms2.empty())
7463     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7464   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7465   int meshDim=ms2[0]->getMeshDimension();
7466   std::vector<const MEDCouplingUMesh *> m1ssm;
7467   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
7468   //
7469   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7470   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
7471   int fake=0,rk=0;
7472   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7473   ret1->alloc(0,1); ret2->alloc(0,1);
7474   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7475     {
7476       if(meshDim!=(*it)->getMeshDimension())
7477         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7478       if(refCoo!=(*it)->getCoords())
7479         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7480       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7481       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7482       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
7483       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7484         {
7485           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7486           m1ssmSingleAuto.push_back(singleCell);
7487           m1ssmSingle.push_back(singleCell);
7488           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7489         }
7490     }
7491   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7492   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7493   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7494   for(std::size_t i=0;i<m1ssm.size();i++)
7495     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7496   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7497   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7498   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7499   return ret0.retn();
7500 }
7501
7502 /*!
7503  * This method returns a newly created DataArrayInt instance.
7504  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7505  */
7506 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7507 {
7508   checkFullyDefined();
7509   const int *conn=_nodal_connec->getConstPointer();
7510   const int *connIndex=_nodal_connec_index->getConstPointer();
7511   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7512   for(const int *w=begin;w!=end;w++)
7513     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7514       ret->pushBackSilent(*w);
7515   return ret.retn();
7516 }
7517
7518 /*!
7519  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7520  * are in [0:getNumberOfCells())
7521  */
7522 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7523 {
7524   checkFullyDefined();
7525   const int *conn=_nodal_connec->getConstPointer();
7526   const int *connI=_nodal_connec_index->getConstPointer();
7527   int nbOfCells=getNumberOfCells();
7528   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7529   int *tmp=new int[nbOfCells];
7530   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7531     {
7532       int j=0;
7533       for(const int *i=connI;i!=connI+nbOfCells;i++)
7534         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7535           tmp[std::distance(connI,i)]=j++;
7536     }
7537   DataArrayInt *ret=DataArrayInt::New();
7538   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7539   ret->copyStringInfoFrom(*da);
7540   int *retPtr=ret->getPointer();
7541   const int *daPtr=da->getConstPointer();
7542   int nbOfElems=da->getNbOfElems();
7543   for(int k=0;k<nbOfElems;k++)
7544     retPtr[k]=tmp[daPtr[k]];
7545   delete [] tmp;
7546   return ret;
7547 }
7548
7549 /*!
7550  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7551  * This method \b works \b for mesh sorted by type.
7552  * cells whose ids is in 'idsPerGeoType' array.
7553  * This method conserves coords and name of mesh.
7554  */
7555 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7556 {
7557   std::vector<int> code=getDistributionOfTypes();
7558   std::size_t nOfTypesInThis=code.size()/3;
7559   int sz=0,szOfType=0;
7560   for(std::size_t i=0;i<nOfTypesInThis;i++)
7561     {
7562       if(code[3*i]!=type)
7563         sz+=code[3*i+1];
7564       else
7565         szOfType=code[3*i+1];
7566     }
7567   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7568     if(*work<0 || *work>=szOfType)
7569       {
7570         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7571         oss << ". It should be in [0," << szOfType << ") !";
7572         throw INTERP_KERNEL::Exception(oss.str().c_str());
7573       }
7574   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7575   int *idsPtr=idsTokeep->getPointer();
7576   int offset=0;
7577   for(std::size_t i=0;i<nOfTypesInThis;i++)
7578     {
7579       if(code[3*i]!=type)
7580         for(int j=0;j<code[3*i+1];j++)
7581           *idsPtr++=offset+j;
7582       else
7583         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7584       offset+=code[3*i+1];
7585     }
7586   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7587   ret->copyTinyInfoFrom(this);
7588   return ret.retn();
7589 }
7590
7591 /*!
7592  * This method returns a vector of size 'this->getNumberOfCells()'.
7593  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7594  */
7595 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7596 {
7597   int ncell=getNumberOfCells();
7598   std::vector<bool> ret(ncell);
7599   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7600   const int *c=getNodalConnectivity()->getConstPointer();
7601   for(int i=0;i<ncell;i++)
7602     {
7603       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7604       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7605       ret[i]=cm.isQuadratic();
7606     }
7607   return ret;
7608 }
7609
7610 /*!
7611  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7612  */
7613 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7614 {
7615   if(other->getType()!=UNSTRUCTURED)
7616     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7617   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7618   return MergeUMeshes(this,otherC);
7619 }
7620
7621 /*!
7622  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7623  * computed by averaging coordinates of cell nodes, so this method is not a right
7624  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7625  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7626  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7627  *          components. The caller is to delete this array using decrRef() as it is
7628  *          no more needed.
7629  *  \throw If the coordinates array is not set.
7630  *  \throw If the nodal connectivity of cells is not defined.
7631  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7632  */
7633 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
7634 {
7635   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7636   int spaceDim=getSpaceDimension();
7637   int nbOfCells=getNumberOfCells();
7638   ret->alloc(nbOfCells,spaceDim);
7639   ret->copyStringInfoFrom(*getCoords());
7640   double *ptToFill=ret->getPointer();
7641   const int *nodal=_nodal_connec->getConstPointer();
7642   const int *nodalI=_nodal_connec_index->getConstPointer();
7643   const double *coor=_coords->getConstPointer();
7644   for(int i=0;i<nbOfCells;i++)
7645     {
7646       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7647       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7648       ptToFill+=spaceDim;
7649     }
7650   return ret.retn();
7651 }
7652
7653 /*!
7654  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7655  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
7656  * 
7657  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7658  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7659  * 
7660  * \sa MEDCouplingUMesh::computeCellCenterOfMass
7661  * \throw If \a this is not fully defined (coordinates and connectivity)
7662  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7663  */
7664 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7665 {
7666   checkFullyDefined();
7667   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7668   int spaceDim=getSpaceDimension();
7669   int nbOfCells=getNumberOfCells();
7670   int nbOfNodes=getNumberOfNodes();
7671   ret->alloc(nbOfCells,spaceDim);
7672   double *ptToFill=ret->getPointer();
7673   const int *nodal=_nodal_connec->getConstPointer();
7674   const int *nodalI=_nodal_connec_index->getConstPointer();
7675   const double *coor=_coords->getConstPointer();
7676   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7677     {
7678       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7679       std::fill(ptToFill,ptToFill+spaceDim,0.);
7680       if(type!=INTERP_KERNEL::NORM_POLYHED)
7681         {
7682           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7683             {
7684               if(*conn>=0 && *conn<nbOfNodes)
7685                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7686               else
7687                 {
7688                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7689                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7690                 }
7691             }
7692           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7693           if(nbOfNodesInCell>0)
7694             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7695           else
7696             {
7697               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7698               throw INTERP_KERNEL::Exception(oss.str().c_str());
7699             }
7700         }
7701       else
7702         {
7703           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7704           s.erase(-1);
7705           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7706             {
7707               if(*it>=0 && *it<nbOfNodes)
7708                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7709               else
7710                 {
7711                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7712                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7713                 }
7714             }
7715           if(!s.empty())
7716             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7717           else
7718             {
7719               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7720               throw INTERP_KERNEL::Exception(oss.str().c_str());
7721             }
7722         }
7723     }
7724   return ret.retn();
7725 }
7726
7727 /*!
7728  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7729  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7730  * are specified via an array of cell ids. 
7731  *  \warning Validity of the specified cell ids is not checked! 
7732  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7733  *  \param [in] begin - an array of cell ids of interest.
7734  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7735  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7736  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7737  *          caller is to delete this array using decrRef() as it is no more needed. 
7738  *  \throw If the coordinates array is not set.
7739  *  \throw If the nodal connectivity of cells is not defined.
7740  *
7741  *  \if ENABLE_EXAMPLES
7742  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7743  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7744  *  \endif
7745  */
7746 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7747 {
7748   DataArrayDouble *ret=DataArrayDouble::New();
7749   int spaceDim=getSpaceDimension();
7750   int nbOfTuple=(int)std::distance(begin,end);
7751   ret->alloc(nbOfTuple,spaceDim);
7752   double *ptToFill=ret->getPointer();
7753   double *tmp=new double[spaceDim];
7754   const int *nodal=_nodal_connec->getConstPointer();
7755   const int *nodalI=_nodal_connec_index->getConstPointer();
7756   const double *coor=_coords->getConstPointer();
7757   for(const int *w=begin;w!=end;w++)
7758     {
7759       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7760       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7761       ptToFill+=spaceDim;
7762     }
7763   delete [] tmp;
7764   return ret;
7765 }
7766
7767 /*!
7768  * 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".
7769  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7770  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7771  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7772  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7773  * 
7774  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7775  * \throw If spaceDim!=3 or meshDim!=2.
7776  * \throw If connectivity of \a this is invalid.
7777  * \throw If connectivity of a cell in \a this points to an invalid node.
7778  */
7779 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7780 {
7781   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
7782   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7783   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7784     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7785   ret->alloc(nbOfCells,4);
7786   double *retPtr(ret->getPointer());
7787   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7788   const double *coor(_coords->begin());
7789   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7790     {
7791       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7792       if(nodalI[1]-nodalI[0]>=3)
7793         {
7794           for(int j=0;j<3;j++)
7795             {
7796               int nodeId(nodal[nodalI[0]+1+j]);
7797               if(nodeId>=0 && nodeId<nbOfNodes)
7798                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7799               else
7800                 {
7801                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7802                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7803                 }
7804             }
7805         }
7806       else
7807         {
7808           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7809           throw INTERP_KERNEL::Exception(oss.str().c_str());
7810         }
7811       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7812       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7813     }
7814   return ret.retn();
7815 }
7816
7817 /*!
7818  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7819  * 
7820  */
7821 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7822 {
7823   if(!da)
7824     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7825   da->checkAllocated();
7826   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7827   ret->setCoords(da);
7828   int nbOfTuples=da->getNumberOfTuples();
7829   MCAuto<DataArrayInt> c=DataArrayInt::New();
7830   MCAuto<DataArrayInt> cI=DataArrayInt::New();
7831   c->alloc(2*nbOfTuples,1);
7832   cI->alloc(nbOfTuples+1,1);
7833   int *cp=c->getPointer();
7834   int *cip=cI->getPointer();
7835   *cip++=0;
7836   for(int i=0;i<nbOfTuples;i++)
7837     {
7838       *cp++=INTERP_KERNEL::NORM_POINT1;
7839       *cp++=i;
7840       *cip++=2*(i+1);
7841     }
7842   ret->setConnectivity(c,cI,true);
7843   return ret.retn();
7844 }
7845 /*!
7846  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7847  * Cells and nodes of
7848  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7849  *  \param [in] mesh1 - the first mesh.
7850  *  \param [in] mesh2 - the second mesh.
7851  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7852  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7853  *          is no more needed.
7854  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7855  *  \throw If the coordinates array is not set in none of the meshes.
7856  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7857  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7858  */
7859 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7860 {
7861   std::vector<const MEDCouplingUMesh *> tmp(2);
7862   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7863   return MergeUMeshes(tmp);
7864 }
7865
7866 /*!
7867  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7868  * Cells and nodes of
7869  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7870  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7871  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7872  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7873  *          is no more needed.
7874  *  \throw If \a a.size() == 0.
7875  *  \throw If \a a[ *i* ] == NULL.
7876  *  \throw If the coordinates array is not set in none of the meshes.
7877  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7878  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7879  */
7880 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7881 {
7882   std::size_t sz=a.size();
7883   if(sz==0)
7884     return MergeUMeshesLL(a);
7885   for(std::size_t ii=0;ii<sz;ii++)
7886     if(!a[ii])
7887       {
7888         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7889         throw INTERP_KERNEL::Exception(oss.str().c_str());
7890       }
7891   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
7892   std::vector< const MEDCouplingUMesh * > aa(sz);
7893   int spaceDim=-3;
7894   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7895     {
7896       const MEDCouplingUMesh *cur=a[i];
7897       const DataArrayDouble *coo=cur->getCoords();
7898       if(coo)
7899         spaceDim=coo->getNumberOfComponents();
7900     }
7901   if(spaceDim==-3)
7902     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7903   for(std::size_t i=0;i<sz;i++)
7904     {
7905       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7906       aa[i]=bb[i];
7907     }
7908   return MergeUMeshesLL(aa);
7909 }
7910
7911 /// @cond INTERNAL
7912
7913 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7914 {
7915   if(a.empty())
7916     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7917   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7918   int meshDim=(*it)->getMeshDimension();
7919   int nbOfCells=(*it)->getNumberOfCells();
7920   int meshLgth=(*it++)->getNodalConnectivityArrayLen();
7921   for(;it!=a.end();it++)
7922     {
7923       if(meshDim!=(*it)->getMeshDimension())
7924         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7925       nbOfCells+=(*it)->getNumberOfCells();
7926       meshLgth+=(*it)->getNodalConnectivityArrayLen();
7927     }
7928   std::vector<const MEDCouplingPointSet *> aps(a.size());
7929   std::copy(a.begin(),a.end(),aps.begin());
7930   MCAuto<DataArrayDouble> pts=MergeNodesArray(aps);
7931   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7932   ret->setCoords(pts);
7933   MCAuto<DataArrayInt> c=DataArrayInt::New();
7934   c->alloc(meshLgth,1);
7935   int *cPtr=c->getPointer();
7936   MCAuto<DataArrayInt> cI=DataArrayInt::New();
7937   cI->alloc(nbOfCells+1,1);
7938   int *cIPtr=cI->getPointer();
7939   *cIPtr++=0;
7940   int offset=0;
7941   int offset2=0;
7942   for(it=a.begin();it!=a.end();it++)
7943     {
7944       int curNbOfCell=(*it)->getNumberOfCells();
7945       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7946       const int *curC=(*it)->_nodal_connec->getConstPointer();
7947       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7948       for(int j=0;j<curNbOfCell;j++)
7949         {
7950           const int *src=curC+curCI[j];
7951           *cPtr++=*src++;
7952           for(;src!=curC+curCI[j+1];src++,cPtr++)
7953             {
7954               if(*src!=-1)
7955                 *cPtr=*src+offset2;
7956               else
7957                 *cPtr=-1;
7958             }
7959         }
7960       offset+=curCI[curNbOfCell];
7961       offset2+=(*it)->getNumberOfNodes();
7962     }
7963   //
7964   ret->setConnectivity(c,cI,true);
7965   return ret.retn();
7966 }
7967
7968 /// @endcond
7969
7970 /*!
7971  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7972  * dimension and sharing the node coordinates array.
7973  * All cells of the first mesh precede all cells of the second mesh
7974  * within the result mesh. 
7975  *  \param [in] mesh1 - the first mesh.
7976  *  \param [in] mesh2 - the second mesh.
7977  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7978  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7979  *          is no more needed.
7980  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7981  *  \throw If the meshes do not share the node coordinates array.
7982  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7983  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7984  */
7985 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7986 {
7987   std::vector<const MEDCouplingUMesh *> tmp(2);
7988   tmp[0]=mesh1; tmp[1]=mesh2;
7989   return MergeUMeshesOnSameCoords(tmp);
7990 }
7991
7992 /*!
7993  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7994  * dimension and sharing the node coordinates array.
7995  * All cells of the *i*-th mesh precede all cells of the
7996  * (*i*+1)-th mesh within the result mesh.
7997  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7998  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7999  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8000  *          is no more needed.
8001  *  \throw If \a a.size() == 0.
8002  *  \throw If \a a[ *i* ] == NULL.
8003  *  \throw If the meshes do not share the node coordinates array.
8004  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
8005  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
8006  */
8007 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
8008 {
8009   if(meshes.empty())
8010     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
8011   for(std::size_t ii=0;ii<meshes.size();ii++)
8012     if(!meshes[ii])
8013       {
8014         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
8015         throw INTERP_KERNEL::Exception(oss.str().c_str());
8016       }
8017   const DataArrayDouble *coords=meshes.front()->getCoords();
8018   int meshDim=meshes.front()->getMeshDimension();
8019   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
8020   int meshLgth=0;
8021   int meshIndexLgth=0;
8022   for(;iter!=meshes.end();iter++)
8023     {
8024       if(coords!=(*iter)->getCoords())
8025         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8026       if(meshDim!=(*iter)->getMeshDimension())
8027         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8028       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
8029       meshIndexLgth+=(*iter)->getNumberOfCells();
8030     }
8031   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
8032   nodal->alloc(meshLgth,1);
8033   int *nodalPtr=nodal->getPointer();
8034   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
8035   nodalIndex->alloc(meshIndexLgth+1,1);
8036   int *nodalIndexPtr=nodalIndex->getPointer();
8037   int offset=0;
8038   for(iter=meshes.begin();iter!=meshes.end();iter++)
8039     {
8040       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8041       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8042       int nbOfCells=(*iter)->getNumberOfCells();
8043       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
8044       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8045       if(iter!=meshes.begin())
8046         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8047       else
8048         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8049       offset+=meshLgth2;
8050     }
8051   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8052   ret->setName("merge");
8053   ret->setMeshDimension(meshDim);
8054   ret->setConnectivity(nodal,nodalIndex,true);
8055   ret->setCoords(coords);
8056   return ret;
8057 }
8058
8059 /*!
8060  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8061  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8062  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8063  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8064  * New" mode are returned for each input mesh.
8065  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8066  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8067  *          valid values [0,1,2], see zipConnectivityTraducer().
8068  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8069  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8070  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8071  *          no more needed.
8072  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8073  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8074  *          is no more needed.
8075  *  \throw If \a meshes.size() == 0.
8076  *  \throw If \a meshes[ *i* ] == NULL.
8077  *  \throw If the meshes do not share the node coordinates array.
8078  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8079  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8080  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8081  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8082  */
8083 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8084 {
8085   //All checks are delegated to MergeUMeshesOnSameCoords
8086   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8087   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8088   corr.resize(meshes.size());
8089   std::size_t nbOfMeshes=meshes.size();
8090   int offset=0;
8091   const int *o2nPtr=o2n->getConstPointer();
8092   for(std::size_t i=0;i<nbOfMeshes;i++)
8093     {
8094       DataArrayInt *tmp=DataArrayInt::New();
8095       int curNbOfCells=meshes[i]->getNumberOfCells();
8096       tmp->alloc(curNbOfCells,1);
8097       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8098       offset+=curNbOfCells;
8099       tmp->setName(meshes[i]->getName());
8100       corr[i]=tmp;
8101     }
8102   return ret.retn();
8103 }
8104
8105 /*!
8106  * Makes all given meshes share the nodal connectivity array. The common connectivity
8107  * array is created by concatenating the connectivity arrays of all given meshes. All
8108  * the given meshes must be of the same space dimension but dimension of cells **can
8109  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8110  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8111  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8112  *  \param [in,out] meshes - a vector of meshes to update.
8113  *  \throw If any of \a meshes is NULL.
8114  *  \throw If the coordinates array is not set in any of \a meshes.
8115  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8116  *  \throw If \a meshes are of different space dimension.
8117  */
8118 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8119 {
8120   std::size_t sz=meshes.size();
8121   if(sz==0 || sz==1)
8122     return;
8123   std::vector< const DataArrayDouble * > coords(meshes.size());
8124   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8125   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8126     {
8127       if((*it))
8128         {
8129           (*it)->checkConnectivityFullyDefined();
8130           const DataArrayDouble *coo=(*it)->getCoords();
8131           if(coo)
8132             *it2=coo;
8133           else
8134             {
8135               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8136               oss << " has no coordinate array defined !";
8137               throw INTERP_KERNEL::Exception(oss.str().c_str());
8138             }
8139         }
8140       else
8141         {
8142           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8143           oss << " is null !";
8144           throw INTERP_KERNEL::Exception(oss.str().c_str());
8145         }
8146     }
8147   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8148   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8149   int offset=(*it)->getNumberOfNodes();
8150   (*it++)->setCoords(res);
8151   for(;it!=meshes.end();it++)
8152     {
8153       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8154       (*it)->setCoords(res);
8155       (*it)->shiftNodeNumbersInConn(offset);
8156       offset+=oldNumberOfNodes;
8157     }
8158 }
8159
8160 /*!
8161  * Merges nodes coincident with a given precision within all given meshes that share
8162  * the nodal connectivity array. The given meshes **can be of different** mesh
8163  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8164  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8165  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8166  *  \param [in,out] meshes - a vector of meshes to update.
8167  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8168  *  \throw If any of \a meshes is NULL.
8169  *  \throw If the \a meshes do not share the same node coordinates array.
8170  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8171  */
8172 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8173 {
8174   if(meshes.empty())
8175     return ;
8176   std::set<const DataArrayDouble *> s;
8177   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8178     {
8179       if(*it)
8180         s.insert((*it)->getCoords());
8181       else
8182         {
8183           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 !";
8184           throw INTERP_KERNEL::Exception(oss.str().c_str());
8185         }
8186     }
8187   if(s.size()!=1)
8188     {
8189       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 !";
8190       throw INTERP_KERNEL::Exception(oss.str().c_str());
8191     }
8192   const DataArrayDouble *coo=*(s.begin());
8193   if(!coo)
8194     return;
8195   //
8196   DataArrayInt *comm,*commI;
8197   coo->findCommonTuples(eps,-1,comm,commI);
8198   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
8199   int oldNbOfNodes=coo->getNumberOfTuples();
8200   int newNbOfNodes;
8201   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8202   if(oldNbOfNodes==newNbOfNodes)
8203     return ;
8204   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8205   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8206     {
8207       (*it)->renumberNodesInConn(o2n->getConstPointer());
8208       (*it)->setCoords(newCoords);
8209     } 
8210 }
8211
8212 /*!
8213  * 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.
8214  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8215  * \param isQuad specifies the policy of connectivity.
8216  * @ret in/out parameter in which the result will be append
8217  */
8218 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8219 {
8220   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8221   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8222   ret.push_back(cm.getExtrudedType());
8223   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8224   switch(flatType)
8225   {
8226     case INTERP_KERNEL::NORM_POINT1:
8227       {
8228         ret.push_back(connBg[1]);
8229         ret.push_back(connBg[1]+nbOfNodesPerLev);
8230         break;
8231       }
8232     case INTERP_KERNEL::NORM_SEG2:
8233       {
8234         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8235         ret.insert(ret.end(),conn,conn+4);
8236         break;
8237       }
8238     case INTERP_KERNEL::NORM_SEG3:
8239       {
8240         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8241         ret.insert(ret.end(),conn,conn+8);
8242         break;
8243       }
8244     case INTERP_KERNEL::NORM_QUAD4:
8245       {
8246         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8247         ret.insert(ret.end(),conn,conn+8);
8248         break;
8249       }
8250     case INTERP_KERNEL::NORM_TRI3:
8251       {
8252         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8253         ret.insert(ret.end(),conn,conn+6);
8254         break;
8255       }
8256     case INTERP_KERNEL::NORM_TRI6:
8257       {
8258         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,
8259           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8260         ret.insert(ret.end(),conn,conn+15);
8261         break;
8262       }
8263     case INTERP_KERNEL::NORM_QUAD8:
8264       {
8265         int conn[20]={
8266           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8267           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8268           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8269         };
8270         ret.insert(ret.end(),conn,conn+20);
8271         break;
8272       }
8273     case INTERP_KERNEL::NORM_POLYGON:
8274       {
8275         std::back_insert_iterator< std::vector<int> > ii(ret);
8276         std::copy(connBg+1,connEnd,ii);
8277         *ii++=-1;
8278         std::reverse_iterator<const int *> rConnBg(connEnd);
8279         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8280         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8281         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8282         for(std::size_t i=0;i<nbOfRadFaces;i++)
8283           {
8284             *ii++=-1;
8285             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8286             std::copy(conn,conn+4,ii);
8287           }
8288         break;
8289       }
8290     default:
8291       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8292   }
8293 }
8294
8295 /*!
8296  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8297  */
8298 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8299 {
8300   std::size_t i, ip1;
8301   double v[3]={0.,0.,0.};
8302   std::size_t sz=std::distance(begin,end);
8303   if(isQuadratic)
8304     sz/=2;
8305   for(i=0;i<sz;i++)
8306     {
8307       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];
8308       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8309       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8310     }
8311   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8312
8313   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8314   // SEG3 forming a circle):
8315   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8316     {
8317       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8318       for(std::size_t j=0;j<sz;j++)
8319         {
8320           if (j%2)  // current point i is quadratic, next point i+1 is standard
8321             {
8322               i = sz+j;
8323               ip1 = (j+1)%sz; // ip1 = "i+1"
8324             }
8325           else      // current point i is standard, next point i+1 is quadratic
8326             {
8327               i = j;
8328               ip1 = j+sz;
8329             }
8330           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8331           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8332           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8333         }
8334       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8335     }
8336   return (ret>0.);
8337 }
8338
8339 /*!
8340  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8341  */
8342 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8343 {
8344   std::vector<std::pair<int,int> > edges;
8345   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8346   const int *bgFace=begin;
8347   for(std::size_t i=0;i<nbOfFaces;i++)
8348     {
8349       const int *endFace=std::find(bgFace+1,end,-1);
8350       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8351       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8352         {
8353           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8354           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8355             return false;
8356           edges.push_back(p1);
8357         }
8358       bgFace=endFace+1;
8359     }
8360   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8361 }
8362
8363 /*!
8364  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8365  */
8366 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8367 {
8368   double vec0[3],vec1[3];
8369   std::size_t sz=std::distance(begin,end);
8370   if(sz%2!=0)
8371     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8372   int nbOfNodes=(int)sz/2;
8373   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8374   const double *pt0=coords+3*begin[0];
8375   const double *pt1=coords+3*begin[nbOfNodes];
8376   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8377   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8378 }
8379
8380 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8381 {
8382   std::size_t sz=std::distance(begin,end);
8383   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8384   std::size_t nbOfNodes(sz/2);
8385   std::copy(begin,end,(int *)tmp);
8386   for(std::size_t j=1;j<nbOfNodes;j++)
8387     {
8388       begin[j]=tmp[nbOfNodes-j];
8389       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8390     }
8391 }
8392
8393 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8394 {
8395   std::size_t sz=std::distance(begin,end);
8396   if(sz!=4)
8397     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
8398   double vec0[3],vec1[3];
8399   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8400   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]; 
8401   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;
8402 }
8403
8404 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8405 {
8406   std::size_t sz=std::distance(begin,end);
8407   if(sz!=5)
8408     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
8409   double vec0[3];
8410   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8411   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8412   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8413 }
8414
8415 /*!
8416  * 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 ) 
8417  * 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
8418  * a 2D space.
8419  *
8420  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8421  * \param [in] coords the coordinates with nb of components exactly equal to 3
8422  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8423  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8424  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8425  */
8426 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8427 {
8428   int nbFaces=std::count(begin+1,end,-1)+1;
8429   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8430   double *vPtr=v->getPointer();
8431   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8432   double *pPtr=p->getPointer();
8433   const int *stFaceConn=begin+1;
8434   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8435     {
8436       const int *endFaceConn=std::find(stFaceConn,end,-1);
8437       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8438       stFaceConn=endFaceConn+1;
8439     }
8440   pPtr=p->getPointer(); vPtr=v->getPointer();
8441   DataArrayInt *comm1=0,*commI1=0;
8442   v->findCommonTuples(eps,-1,comm1,commI1);
8443   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8444   const int *comm1Ptr=comm1->getConstPointer();
8445   const int *commI1Ptr=commI1->getConstPointer();
8446   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8447   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8448   //
8449   MCAuto<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8450   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8451   mm->finishInsertingCells();
8452   //
8453   for(int i=0;i<nbOfGrps1;i++)
8454     {
8455       int vecId=comm1Ptr[commI1Ptr[i]];
8456       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8457       DataArrayInt *comm2=0,*commI2=0;
8458       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8459       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8460       const int *comm2Ptr=comm2->getConstPointer();
8461       const int *commI2Ptr=commI2->getConstPointer();
8462       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8463       for(int j=0;j<nbOfGrps2;j++)
8464         {
8465           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8466             {
8467               res->insertAtTheEnd(begin,end);
8468               res->pushBackSilent(-1);
8469             }
8470           else
8471             {
8472               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8473               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
8474               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8475               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8476               MCAuto<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8477               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8478               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8479               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8480               const int *idsNodePtr=idsNode->getConstPointer();
8481               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];
8482               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8483               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8484               if(std::abs(norm)>eps)
8485                 {
8486                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8487                   mm3->rotate(center,vec,angle);
8488                 }
8489               mm3->changeSpaceDimension(2);
8490               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8491               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8492               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8493               int nbOfCells=mm4->getNumberOfCells();
8494               for(int k=0;k<nbOfCells;k++)
8495                 {
8496                   int l=0;
8497                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8498                     res->pushBackSilent(idsNodePtr[*work]);
8499                   res->pushBackSilent(-1);
8500                 }
8501             }
8502         }
8503     }
8504   res->popBackSilent();
8505 }
8506
8507 /*!
8508  * 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
8509  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8510  * 
8511  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8512  * \param [in] coords coordinates expected to have 3 components.
8513  * \param [in] begin start of the nodal connectivity of the face.
8514  * \param [in] end end of the nodal connectivity (excluded) of the face.
8515  * \param [out] v the normalized vector of size 3
8516  * \param [out] p the pos of plane
8517  */
8518 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8519 {
8520   std::size_t nbPoints=std::distance(begin,end);
8521   if(nbPoints<3)
8522     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8523   double vec[3]={0.,0.,0.};
8524   std::size_t j=0;
8525   bool refFound=false;
8526   for(;j<nbPoints-1 && !refFound;j++)
8527     {
8528       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8529       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8530       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8531       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8532       if(norm>eps)
8533         {
8534           refFound=true;
8535           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8536         }
8537     }
8538   for(std::size_t i=j;i<nbPoints-1;i++)
8539     {
8540       double curVec[3];
8541       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8542       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8543       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8544       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8545       if(norm<eps)
8546         continue;
8547       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8548       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];
8549       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8550       if(norm>eps)
8551         {
8552           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8553           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8554           return ;
8555         }
8556     }
8557   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8558 }
8559
8560 /*!
8561  * This method tries to obtain a well oriented polyhedron.
8562  * If the algorithm fails, an exception will be thrown.
8563  */
8564 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8565 {
8566   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8567   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8568   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8569   isPerm[0]=true;
8570   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8571   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8572   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8573   //
8574   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8575     {
8576       bgFace=begin;
8577       std::size_t smthChanged=0;
8578       for(std::size_t i=0;i<nbOfFaces;i++)
8579         {
8580           endFace=std::find(bgFace+1,end,-1);
8581           nbOfEdgesInFace=std::distance(bgFace,endFace);
8582           if(!isPerm[i])
8583             {
8584               bool b;
8585               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8586                 {
8587                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8588                   std::pair<int,int> p2(p1.second,p1.first);
8589                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8590                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8591                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8592                 }
8593               if(isPerm[i])
8594                 { 
8595                   if(!b)
8596                     std::reverse(bgFace+1,endFace);
8597                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8598                     {
8599                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8600                       std::pair<int,int> p2(p1.second,p1.first);
8601                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8602                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8603                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8604                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8605                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8606                       if(it!=edgesOK.end())
8607                         {
8608                           edgesOK.erase(it);
8609                           edgesFinished.push_back(p1);
8610                         }
8611                       else
8612                         edgesOK.push_back(p1);
8613                     }
8614                 }
8615             }
8616           bgFace=endFace+1;
8617         }
8618       if(smthChanged==0)
8619         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8620     }
8621   if(!edgesOK.empty())
8622     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8623   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8624     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8625       bgFace=begin;
8626       for(std::size_t i=0;i<nbOfFaces;i++)
8627         {
8628           endFace=std::find(bgFace+1,end,-1);
8629           std::reverse(bgFace+1,endFace);
8630           bgFace=endFace+1;
8631         }
8632     }
8633 }
8634
8635 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8636 {
8637   int nbOfNodesExpected(skin->getNumberOfNodes());
8638   const int *n2oPtr(n2o->getConstPointer());
8639   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8640   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8641   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8642   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8643   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8644   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8645   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8646   if(nbOfNodesExpected<1)
8647     return ret.retn();
8648   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8649   *work++=n2oPtr[prevNode];
8650   for(int i=1;i<nbOfNodesExpected;i++)
8651     {
8652       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8653         {
8654           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8655           conn.erase(prevNode);
8656           if(conn.size()==1)
8657             {
8658               int curNode(*(conn.begin()));
8659               *work++=n2oPtr[curNode];
8660               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8661               shar.erase(prevCell);
8662               if(shar.size()==1)
8663                 {
8664                   prevCell=*(shar.begin());
8665                   prevNode=curNode;
8666                 }
8667               else
8668                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8669             }
8670           else
8671             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8672         }
8673       else
8674         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8675     }
8676   return ret.retn();
8677 }
8678
8679 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8680 {
8681   int nbOfNodesExpected(skin->getNumberOfNodes());
8682   int nbOfTurn(nbOfNodesExpected/2);
8683   const int *n2oPtr(n2o->getConstPointer());
8684   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8685   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8686   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8687   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8688   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8689   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8690   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8691   if(nbOfNodesExpected<1)
8692     return ret.retn();
8693   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8694   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8695   for(int i=1;i<nbOfTurn;i++)
8696     {
8697       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8698         {
8699           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8700           conn.erase(prevNode);
8701           if(conn.size()==1)
8702             {
8703               int curNode(*(conn.begin()));
8704               *work=n2oPtr[curNode];
8705               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8706               shar.erase(prevCell);
8707               if(shar.size()==1)
8708                 {
8709                   int curCell(*(shar.begin()));
8710                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8711                   prevCell=curCell;
8712                   prevNode=curNode;
8713                   work++;
8714                 }
8715               else
8716                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8717             }
8718           else
8719             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8720         }
8721       else
8722         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8723     }
8724   return ret.retn();
8725 }
8726
8727 /*!
8728  * This method makes the assumption spacedimension == meshdimension == 2.
8729  * This method works only for linear cells.
8730  * 
8731  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8732  */
8733 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8734 {
8735   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8736     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8737   MCAuto<MEDCouplingUMesh> skin(computeSkin());
8738   int oldNbOfNodes(skin->getNumberOfNodes());
8739   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
8740   int nbOfNodesExpected(skin->getNumberOfNodes());
8741   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8742   int nbCells(skin->getNumberOfCells());
8743   if(nbCells==nbOfNodesExpected)
8744     return buildUnionOf2DMeshLinear(skin,n2o);
8745   else if(2*nbCells==nbOfNodesExpected)
8746     return buildUnionOf2DMeshQuadratic(skin,n2o);
8747   else
8748     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8749 }
8750
8751 /*!
8752  * This method makes the assumption spacedimension == meshdimension == 3.
8753  * This method works only for linear cells.
8754  * 
8755  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8756  */
8757 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8758 {
8759   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8760     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8761   MCAuto<MEDCouplingUMesh> m=computeSkin();
8762   const int *conn=m->getNodalConnectivity()->getConstPointer();
8763   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8764   int nbOfCells=m->getNumberOfCells();
8765   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8766   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8767   if(nbOfCells<1)
8768     return ret.retn();
8769   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8770   for(int i=1;i<nbOfCells;i++)
8771     {
8772       *work++=-1;
8773       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8774     }
8775   return ret.retn();
8776 }
8777
8778 /*!
8779  * \brief Creates a graph of cell neighbors
8780  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8781  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8782  *  For example
8783  *  - index:  0 3 5 6 6
8784  *  - value:  1 2 3 2 3 3
8785  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8786  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8787  */
8788 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8789 {
8790   checkConnectivityFullyDefined();
8791
8792   int meshDim = this->getMeshDimension();
8793   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
8794   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
8795   this->getReverseNodalConnectivity(revConn,indexr);
8796   const int* indexr_ptr=indexr->getConstPointer();
8797   const int* revConn_ptr=revConn->getConstPointer();
8798
8799   const MEDCoupling::DataArrayInt* index;
8800   const MEDCoupling::DataArrayInt* conn;
8801   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8802   index=this->getNodalConnectivityIndex();
8803   int nbCells=this->getNumberOfCells();
8804   const int* index_ptr=index->getConstPointer();
8805   const int* conn_ptr=conn->getConstPointer();
8806
8807   //creating graph arcs (cell to cell relations)
8808   //arcs are stored in terms of (index,value) notation
8809   // 0 3 5 6 6
8810   // 1 2 3 2 3 3
8811   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8812   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8813
8814   //warning here one node have less than or equal effective number of cell with it
8815   //but cell could have more than effective nodes
8816   //because other equals nodes in other domain (with other global inode)
8817   std::vector <int> cell2cell_index(nbCells+1,0);
8818   std::vector <int> cell2cell;
8819   cell2cell.reserve(3*nbCells);
8820
8821   for (int icell=0; icell<nbCells;icell++)
8822     {
8823       std::map<int,int > counter;
8824       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8825         {
8826           int inode=conn_ptr[iconn];
8827           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8828             {
8829               int icell2=revConn_ptr[iconnr];
8830               std::map<int,int>::iterator iter=counter.find(icell2);
8831               if (iter!=counter.end()) (iter->second)++;
8832               else counter.insert(std::make_pair(icell2,1));
8833             }
8834         }
8835       for (std::map<int,int>::const_iterator iter=counter.begin();
8836            iter!=counter.end(); iter++)
8837         if (iter->second >= meshDim)
8838           {
8839             cell2cell_index[icell+1]++;
8840             cell2cell.push_back(iter->first);
8841           }
8842     }
8843   indexr->decrRef();
8844   revConn->decrRef();
8845   cell2cell_index[0]=0;
8846   for (int icell=0; icell<nbCells;icell++)
8847     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8848
8849   //filling up index and value to create skylinearray structure
8850   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8851   return array;
8852 }
8853
8854 /*!
8855  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8856  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8857  */
8858 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8859 {
8860   double *w=zipFrmt;
8861   if(spaceDim==3)
8862     for(int i=0;i<nbOfNodesInCell;i++)
8863       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8864   else if(spaceDim==2)
8865     {
8866       for(int i=0;i<nbOfNodesInCell;i++)
8867         {
8868           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8869           *w++=0.;
8870         }
8871     }
8872   else
8873     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8874 }
8875
8876 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8877 {
8878   int nbOfCells=getNumberOfCells();
8879   if(nbOfCells<=0)
8880     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8881   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};
8882   ofs << "  <" << getVTKDataSetType() << ">\n";
8883   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8884   ofs << "      <PointData>\n" << pointData << std::endl;
8885   ofs << "      </PointData>\n";
8886   ofs << "      <CellData>\n" << cellData << std::endl;
8887   ofs << "      </CellData>\n";
8888   ofs << "      <Points>\n";
8889   if(getSpaceDimension()==3)
8890     _coords->writeVTK(ofs,8,"Points",byteData);
8891   else
8892     {
8893       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8894       coo->writeVTK(ofs,8,"Points",byteData);
8895     }
8896   ofs << "      </Points>\n";
8897   ofs << "      <Cells>\n";
8898   const int *cPtr=_nodal_connec->getConstPointer();
8899   const int *cIPtr=_nodal_connec_index->getConstPointer();
8900   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8901   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8902   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8903   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8904   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8905   int szFaceOffsets=0,szConn=0;
8906   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8907     {
8908       *w2=cPtr[cIPtr[i]];
8909       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8910         {
8911           *w1=-1;
8912           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8913           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8914         }
8915       else
8916         {
8917           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8918           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8919           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8920           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8921           w4=std::copy(c.begin(),c.end(),w4);
8922         }
8923     }
8924   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8925   types->writeVTK(ofs,8,"UInt8","types",byteData);
8926   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8927   if(szFaceOffsets!=0)
8928     {//presence of Polyhedra
8929       connectivity->reAlloc(szConn);
8930       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8931       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8932       w1=faces->getPointer();
8933       for(int i=0;i<nbOfCells;i++)
8934         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8935           {
8936             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8937             *w1++=nbFaces;
8938             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8939             for(int j=0;j<nbFaces;j++)
8940               {
8941                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8942                 *w1++=(int)std::distance(w6,w5);
8943                 w1=std::copy(w6,w5,w1);
8944                 w6=w5+1;
8945               }
8946           }
8947       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8948     }
8949   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8950   ofs << "      </Cells>\n";
8951   ofs << "    </Piece>\n";
8952   ofs << "  </" << getVTKDataSetType() << ">\n";
8953 }
8954
8955 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8956 {
8957   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8958   if(_mesh_dim==-2)
8959     { stream << " Not set !"; return ; }
8960   stream << " Mesh dimension : " << _mesh_dim << ".";
8961   if(_mesh_dim==-1)
8962     return ;
8963   if(!_coords)
8964     { stream << " No coordinates set !"; return ; }
8965   if(!_coords->isAllocated())
8966     { stream << " Coordinates set but not allocated !"; return ; }
8967   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8968   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8969   if(!_nodal_connec_index)
8970     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8971   if(!_nodal_connec_index->isAllocated())
8972     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8973   int lgth=_nodal_connec_index->getNumberOfTuples();
8974   int cpt=_nodal_connec_index->getNumberOfComponents();
8975   if(cpt!=1 || lgth<1)
8976     return ;
8977   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8978 }
8979
8980 std::string MEDCouplingUMesh::getVTKDataSetType() const
8981 {
8982   return std::string("UnstructuredGrid");
8983 }
8984
8985 std::string MEDCouplingUMesh::getVTKFileExtension() const
8986 {
8987   return std::string("vtu");
8988 }
8989
8990 /*!
8991  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8992  * returns a result mesh constituted by polygons.
8993  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8994  * all nodes from m2.
8995  * The meshes should be in 2D space. In
8996  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8997  * meshes.
8998  *  \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
8999  *                      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)
9000  *  \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
9001  *                      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)
9002  *  \param [in] eps - precision used to detect coincident mesh entities.
9003  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
9004  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
9005  *         this array using decrRef() as it is no more needed.
9006  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
9007  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
9008  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
9009  *         any cell of \a m2. The caller is to delete this array using decrRef() as
9010  *         it is no more needed.  
9011  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
9012  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
9013  *         is no more needed.  
9014  *  \throw If the coordinates array is not set in any of the meshes.
9015  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
9016  *  \throw If any of the meshes is not a 2D mesh in 2D space.
9017  *
9018  *  \sa conformize2D, mergeNodes
9019  */
9020 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9021                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9022 {
9023   if(!m1 || !m2)
9024     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9025   m1->checkFullyDefined();
9026   m2->checkFullyDefined();
9027   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9028     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
9029
9030   // Step 1: compute all edge intersections (new nodes)
9031   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9032   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9033   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9034   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9035   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9036                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9037                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9038   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9039   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9040   MCAuto<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9041
9042   // Step 2: re-order newly created nodes according to the ordering found in m2
9043   std::vector< std::vector<int> > intersectEdge2;
9044   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9045   subDiv2.clear(); dd5=0; dd6=0;
9046
9047   // Step 3:
9048   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9049   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9050   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9051                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9052
9053   // Step 4: Prepare final result:
9054   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
9055   addCooDa->alloc((int)(addCoo.size())/2,2);
9056   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9057   MCAuto<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9058   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9059   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9060   std::vector<const DataArrayDouble *> coordss(4);
9061   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9062   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9063   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9064   MCAuto<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9065   MCAuto<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9066   MCAuto<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9067   MCAuto<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9068   ret->setConnectivity(conn,connI,true);
9069   ret->setCoords(coo);
9070   cellNb1=c1.retn(); cellNb2=c2.retn();
9071   return ret.retn();
9072 }
9073
9074 /// @cond INTERNAL
9075
9076 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9077 {
9078   if(candidates.empty())
9079     return false;
9080   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9081     {
9082       const std::vector<int>& pool(intersectEdge1[*it]);
9083       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9084       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9085         {
9086           retVal=*it+1;
9087           return true;
9088         }
9089       tmp[0]=stop; tmp[1]=start;
9090       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9091         {
9092           retVal=-*it-1;
9093           return true;
9094         }
9095     }
9096   return false;
9097 }
9098
9099 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,
9100                                      MCAuto<DataArrayInt>& idsInRetColinear, MCAuto<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9101 {
9102   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9103   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9104   int nCells(mesh1D->getNumberOfCells());
9105   if(nCells!=(int)intersectEdge2.size())
9106     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9107   const DataArrayDouble *coo2(mesh1D->getCoords());
9108   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9109   const double *coo2Ptr(coo2->begin());
9110   int offset1(coords1->getNumberOfTuples());
9111   int offset2(offset1+coo2->getNumberOfTuples());
9112   int offset3(offset2+addCoo.size()/2);
9113   std::vector<double> addCooQuad;
9114   MCAuto<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9115   int tmp[4],cicnt(0),kk(0);
9116   for(int i=0;i<nCells;i++)
9117     {
9118       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
9119       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9120       const std::vector<int>& subEdges(intersectEdge2[i]);
9121       int nbSubEdge(subEdges.size()/2);
9122       for(int j=0;j<nbSubEdge;j++,kk++)
9123         {
9124           MCAuto<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));
9125           MCAuto<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9126           INTERP_KERNEL::Edge *e2Ptr(e2);
9127           std::map<int,int>::const_iterator itm;
9128           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9129             {
9130               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9131               itm=mergedNodes.find(subEdges[2*j]);
9132               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9133               itm=mergedNodes.find(subEdges[2*j+1]);
9134               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9135               tmp[3]=offset3+(int)addCooQuad.size()/2;
9136               double tmp2[2];
9137               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9138               cicnt+=4;
9139               cOut->insertAtTheEnd(tmp,tmp+4);
9140               ciOut->pushBackSilent(cicnt);
9141             }
9142           else
9143             {
9144               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9145               itm=mergedNodes.find(subEdges[2*j]);
9146               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9147               itm=mergedNodes.find(subEdges[2*j+1]);
9148               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9149               cicnt+=3;
9150               cOut->insertAtTheEnd(tmp,tmp+3);
9151               ciOut->pushBackSilent(cicnt);
9152             }
9153           int tmp00;
9154           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9155             {
9156               idsInRetColinear->pushBackSilent(kk);
9157               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9158             }
9159         }
9160       e->decrRef();
9161     }
9162   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9163   ret->setConnectivity(cOut,ciOut,true);
9164   MCAuto<DataArrayDouble> arr3(DataArrayDouble::New());
9165   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9166   MCAuto<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9167   std::vector<const DataArrayDouble *> coordss(4);
9168   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9169   MCAuto<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9170   ret->setCoords(arr);
9171   return ret.retn();
9172 }
9173
9174 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9175 {
9176   std::vector<int> allEdges;
9177   for(const int *it2(descBg);it2!=descEnd;it2++)
9178     {
9179       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9180       if(*it2>0)
9181         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9182       else
9183         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9184     }
9185   std::size_t nb(allEdges.size());
9186   if(nb%2!=0)
9187     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9188   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9189   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9190   ret->setCoords(coords);
9191   ret->allocateCells(1);
9192   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9193   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9194     connOut[kk]=allEdges[2*kk];
9195   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9196   return ret.retn();
9197 }
9198
9199 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9200 {
9201   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9202   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9203   std::size_t ii(0);
9204   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9205   if(sz!=std::distance(descBg,descEnd))
9206     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9207   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9208   std::vector<int> allEdges,centers;
9209   const double *coordsPtr(coords->begin());
9210   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9211   int offset(coords->getNumberOfTuples());
9212   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9213     {
9214       INTERP_KERNEL::NormalizedCellType typeOfSon;
9215       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9216       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9217       if(*it2>0)
9218         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9219       else
9220         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9221       if(edge1.size()==2)
9222         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9223       else
9224         {//the current edge has been subsplit -> create corresponding centers.
9225           std::size_t nbOfCentersToAppend(edge1.size()/2);
9226           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9227           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9228           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9229           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9230             {
9231               double tmpp[2];
9232               const double *aa(coordsPtr+2*(*it3++));
9233               const double *bb(coordsPtr+2*(*it3++));
9234               ee->getMiddleOfPoints(aa,bb,tmpp);
9235               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9236               centers.push_back(offset+k);
9237             }
9238         }
9239     }
9240   std::size_t nb(allEdges.size());
9241   if(nb%2!=0)
9242     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9243   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9244   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9245   if(addCoo->empty())
9246     ret->setCoords(coords);
9247   else
9248     {
9249       addCoo->rearrange(2);
9250       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9251       ret->setCoords(addCoo);
9252     }
9253   ret->allocateCells(1);
9254   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9255   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9256     connOut[kk]=allEdges[2*kk];
9257   connOut.insert(connOut.end(),centers.begin(),centers.end());
9258   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9259   return ret.retn();
9260 }
9261
9262 /*!
9263  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9264  * of those edges.
9265  *
9266  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9267  */
9268 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9269 {
9270   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9271   if(!cm.isQuadratic())
9272     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9273   else
9274     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9275 }
9276
9277 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edges)
9278 {
9279   bool isQuad(false);
9280   for(std::vector< MCAuto<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9281     {
9282       const INTERP_KERNEL::Edge *ee(*it);
9283       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9284         isQuad=true;
9285     }
9286   if(!isQuad)
9287     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9288   else
9289     {
9290       const double *coo(mesh2D->getCoords()->begin());
9291       std::size_t sz(conn.size());
9292       std::vector<double> addCoo;
9293       std::vector<int> conn2(conn);
9294       int offset(mesh2D->getNumberOfNodes());
9295       for(std::size_t i=0;i<sz;i++)
9296         {
9297           double tmp[2];
9298           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9299           addCoo.insert(addCoo.end(),tmp,tmp+2);
9300           conn2.push_back(offset+(int)i);
9301         }
9302       mesh2D->getCoords()->rearrange(1);
9303       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9304       mesh2D->getCoords()->rearrange(2);
9305       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9306     }
9307 }
9308
9309 /*!
9310  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9311  *
9312  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9313  * a set of edges defined in \a splitMesh1D.
9314  */
9315 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edge1BisPtr,
9316                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& out1)
9317 {
9318   std::size_t nb(edge1Bis.size()/2);
9319   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9320   int iEnd(splitMesh1D->getNumberOfCells());
9321   if(iEnd==0)
9322     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9323   std::size_t ii,jj;
9324   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9325   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9326   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9327   //
9328   if(jj==nb)
9329     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9330       out0.resize(1); out1.resize(1);
9331       std::vector<int>& connOut(out0[0]);
9332       connOut.resize(nbOfEdgesOf2DCellSplit);
9333       std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9334       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9335       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9336         {
9337           connOut[kk]=edge1Bis[2*kk];
9338           edgesPtr[kk]=edge1BisPtr[2*kk];
9339         }
9340     }
9341   else
9342     {
9343       // [i,iEnd[ contains the
9344       out0.resize(2); out1.resize(2);
9345       std::vector<int>& connOutLeft(out0[0]);
9346       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9347       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9348       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eright(out1[1]);
9349       for(std::size_t k=ii;k<jj+1;k++)
9350         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9351       std::vector< MCAuto<INTERP_KERNEL::Edge> > ees(iEnd);
9352       for(int ik=0;ik<iEnd;ik++)
9353         {
9354           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9355           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9356           ees[ik]=ee;
9357         }
9358       for(int ik=iEnd-1;ik>=0;ik--)
9359         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9360       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9361         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9362       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9363       for(int ik=0;ik<iEnd;ik++)
9364         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9365       eright.insert(eright.end(),ees.begin(),ees.end());
9366     }
9367 }
9368
9369 /// @endcond
9370
9371 /// @cond INTERNAL
9372
9373 struct CellInfo
9374 {
9375 public:
9376   CellInfo() { }
9377   CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9378 public:
9379   std::vector<int> _edges;
9380   std::vector< MCAuto<INTERP_KERNEL::Edge> > _edges_ptr;
9381 };
9382
9383 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr)
9384 {
9385   std::size_t nbe(edges.size());
9386   std::vector<int> edges2(2*nbe); std::vector< MCAuto<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9387   for(std::size_t i=0;i<nbe;i++)
9388     {
9389       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9390       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9391     }
9392   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9393   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9394   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9395 }
9396
9397 class EdgeInfo
9398 {
9399 public:
9400   EdgeInfo(int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9401   EdgeInfo(int istart, int iend, int pos, const MCAuto<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9402   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9403   void somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9404   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9405 private:
9406   int _istart;
9407   int _iend;
9408   MCAuto<MEDCouplingUMesh> _mesh;
9409   MCAuto<INTERP_KERNEL::Edge> _edge;
9410   int _left;
9411   int _right;
9412 };
9413
9414 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9415 {
9416   const MEDCouplingUMesh *mesh(_mesh);
9417   if(mesh)
9418     return ;
9419   if(_right<pos)
9420     return ;
9421   if(_left>pos)
9422     { _left++; _right++; return ; }
9423   if(_right==pos)
9424     {
9425       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9426       if((isLeft && isRight) || (!isLeft && !isRight))
9427         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9428       if(isLeft)
9429         return ;
9430       if(isRight)
9431         {
9432           _right++;
9433           return ;
9434         }
9435     }
9436   if(_left==pos)
9437     {
9438       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9439       if((isLeft && isRight) || (!isLeft && !isRight))
9440         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9441       if(isLeft)
9442         {
9443           _right++;
9444           return ;
9445         }
9446       if(isRight)
9447         {
9448           _left++;
9449           _right++;
9450           return ;
9451         }
9452     }
9453 }
9454
9455 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9456 {
9457   const MEDCouplingUMesh *mesh(_mesh);
9458   if(!mesh)
9459     {
9460       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9461     }
9462   else
9463     {// not fully splitting cell case
9464       if(mesh2D->getNumberOfCells()==1)
9465         {//little optimization. 1 cell no need to find in which cell mesh is !
9466           neighbors[0]=offset; neighbors[1]=offset;
9467           return;
9468         }
9469       else
9470         {
9471           MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9472           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9473           if(cellId==-1)
9474             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9475           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9476         }
9477     }
9478 }
9479
9480 class VectorOfCellInfo
9481 {
9482 public:
9483   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9484   std::size_t size() const { return _pool.size(); }
9485   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9486   void setMeshAt(int pos, const MCAuto<MEDCouplingUMesh>& mesh, int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& edgePtrs);
9487   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9488   const std::vector< MCAuto<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9489   MCAuto<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9490   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9491 private:
9492   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9493   void updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9494   const CellInfo& get(int pos) const;
9495   CellInfo& get(int pos);
9496 private:
9497   std::vector<CellInfo> _pool;
9498   MCAuto<MEDCouplingUMesh> _ze_mesh;
9499   std::vector<EdgeInfo> _edge_info;
9500 };
9501
9502 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9503 {
9504   _pool[0]._edges=edges;
9505   _pool[0]._edges_ptr=edgesPtr;
9506 }
9507
9508 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9509 {
9510   if(_pool.empty())
9511     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9512   if(_pool.size()==1)
9513     return 0;
9514   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9515   if(!zeMesh)
9516     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9517   MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9518   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9519 }
9520
9521 void VectorOfCellInfo::setMeshAt(int pos, const MCAuto<MEDCouplingUMesh>& mesh, int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& edgePtrs)
9522 {
9523   get(pos);//to check pos
9524   bool isFast(pos==0 && _pool.size()==1);
9525   std::size_t sz(edges.size());
9526   // dealing with edges
9527   if(sz==1)
9528     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9529   else
9530     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9531   //
9532   std::vector<CellInfo> pool(_pool.size()-1+sz);
9533   for(int i=0;i<pos;i++)
9534     pool[i]=_pool[i];
9535   for(std::size_t j=0;j<sz;j++)
9536     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9537   for(int i=pos+1;i<(int)_pool.size();i++)
9538     pool[i+sz-1]=_pool[i];
9539   _pool=pool;
9540   //
9541   if(sz==2)
9542     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9543   //
9544   if(isFast)
9545     {
9546       _ze_mesh=mesh;
9547       return ;
9548     }
9549   //
9550   std::vector< MCAuto<MEDCouplingUMesh> > ms;
9551   if(pos>0)
9552     {
9553       MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(0,pos,true)));
9554       ms.push_back(elt);
9555     }
9556   ms.push_back(mesh);
9557   if(pos<_ze_mesh->getNumberOfCells()-1)
9558   {
9559     MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(pos+1,_ze_mesh->getNumberOfCells(),true)));
9560     ms.push_back(elt);
9561   }
9562   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9563   for(std::size_t j=0;j<ms2.size();j++)
9564     ms2[j]=ms[j];
9565   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9566 }
9567
9568 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9569 {
9570   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9571 }
9572
9573 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9574 {
9575   if(pos<0)
9576     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9577   int ret(0);
9578   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9579     {
9580       if((*it).isInMyRange(pos))
9581         return ret;
9582     }
9583   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9584 }
9585
9586 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9587 {
9588   get(pos);//to check;
9589   if(_edge_info.empty())
9590     return ;
9591   std::size_t sz(_edge_info.size()-1);
9592   for(std::size_t i=0;i<sz;i++)
9593     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9594 }
9595
9596 const CellInfo& VectorOfCellInfo::get(int pos) const
9597 {
9598   if(pos<0 || pos>=(int)_pool.size())
9599     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9600   return _pool[pos];
9601 }
9602
9603 CellInfo& VectorOfCellInfo::get(int pos)
9604 {
9605   if(pos<0 || pos>=(int)_pool.size())
9606     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9607   return _pool[pos];
9608 }
9609
9610 /*!
9611  * Given :
9612  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9613  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9614  *
9615  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9616  *
9617  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9618  *
9619  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9620  */
9621 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9622                                          MCAuto<DataArrayInt>& idsLeftRight)
9623 {
9624   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9625   if(nbCellsInSplitMesh1D==0)
9626     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9627   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9628   std::size_t nb(allEdges.size()),jj;
9629   if(nb%2!=0)
9630     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9631   std::vector<int> edge1Bis(nb*2);
9632   std::vector< MCAuto<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9633   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9634   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9635   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9636   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9637   //
9638   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9639   int *idsLeftRightPtr(idsLeftRight->getPointer());
9640   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9641   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9642     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9643       int iEnd(iStart);
9644       for(;iEnd<nbCellsInSplitMesh1D;)
9645         {
9646           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9647           if(jj!=nb)
9648             break;
9649           else
9650             iEnd++;
9651         }
9652       if(iEnd<nbCellsInSplitMesh1D)
9653         iEnd++;
9654       //
9655       MCAuto<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelfSlice(iStart,iEnd,1,true)));
9656       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9657       //
9658       MCAuto<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9659       retTmp->setCoords(splitMesh1D->getCoords());
9660       retTmp->allocateCells();
9661
9662       std::vector< std::vector<int> > out0;
9663       std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > > out1;
9664
9665       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9666       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9667         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9668       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9669       //
9670       iStart=iEnd;
9671     }
9672   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9673     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9674   return pool.getZeMesh().retn();
9675 }
9676
9677 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9678                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9679                                      MCAuto<DataArrayInt>& idsLeftRight)
9680 {
9681   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9682   //
9683   std::vector<int> allEdges;
9684   std::vector< MCAuto<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9685   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9686     {
9687       int edgeId(std::abs(*it)-1);
9688       std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9689       MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9690       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9691       if(*it>0)
9692         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9693       else
9694         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9695       std::size_t sz(edge1.size());
9696       for(std::size_t cnt=0;cnt<sz;cnt++)
9697         allEdgesPtr.push_back(ee);
9698     }
9699   //
9700   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9701 }
9702
9703 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9704 {
9705   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9706     {//easy case comparison not
9707       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9708     }
9709   else if(typ1.isQuadratic() && typ2.isQuadratic())
9710     {
9711       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9712       if(!status0)
9713         return false;
9714       if(conn1[2]==conn2[2])
9715         return true;
9716       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9717       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9718       return dist<eps;
9719     }
9720   else
9721     {//only one is quadratic
9722       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9723       if(!status0)
9724         return false;
9725       const double *a(0),*bb(0),*be(0);
9726       if(typ1.isQuadratic())
9727         {
9728           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9729         }
9730       else
9731         {
9732           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9733         }
9734       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9735       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9736       return dist<eps;
9737     }
9738 }
9739
9740 /*!
9741  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9742  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9743  *
9744  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9745  */
9746 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9747 {
9748   if(candidatesIn2DEnd==candidatesIn2DBg)
9749     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9750   const double *coo(mesh2DSplit->getCoords()->begin());
9751   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9752     return *candidatesIn2DBg;
9753   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9754   MCAuto<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9755   if(cellIdInMesh1DSplitRelative<0)
9756     cur1D->changeOrientationOfCells();
9757   const int *c1D(cur1D->getNodalConnectivity()->begin());
9758   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9759   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9760     {
9761       MCAuto<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9762       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9763       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9764       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9765       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9766       for(unsigned it2=0;it2<sz;it2++)
9767         {
9768           INTERP_KERNEL::NormalizedCellType typeOfSon;
9769           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9770           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9771           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9772             return *it;
9773         }
9774     }
9775   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9776 }
9777
9778 /// @endcond
9779
9780 /*!
9781  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9782  * 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
9783  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9784  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9785  *
9786  * \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
9787  *                      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)
9788  * \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
9789  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9790  * \param [in] eps - precision used to perform intersections and localization operations.
9791  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9792  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9793  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9794  *                               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.
9795  * \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
9796  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9797  *                               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.
9798  *
9799  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9800  */
9801 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9802 {
9803   if(!mesh2D || !mesh1D)
9804     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9805   mesh2D->checkFullyDefined();
9806   mesh1D->checkFullyDefined();
9807   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9808   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9809     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9810   // Step 1: compute all edge intersections (new nodes)
9811   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9812   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9813   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9814   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9815   //
9816   // Build desc connectivity
9817   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9818   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9819   MCAuto<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9820   std::map<int,int> mergedNodes;
9821   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9822   // use mergeNodes to fix intersectEdge1
9823   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9824     {
9825       std::size_t n((*it0).size()/2);
9826       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9827       std::map<int,int>::const_iterator it1;
9828       it1=mergedNodes.find(eltStart);
9829       if(it1!=mergedNodes.end())
9830         (*it0)[0]=(*it1).second;
9831       it1=mergedNodes.find(eltEnd);
9832       if(it1!=mergedNodes.end())
9833         (*it0)[2*n-1]=(*it1).second;
9834     }
9835   //
9836   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
9837   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9838   // Step 2: re-order newly created nodes according to the ordering found in m2
9839   std::vector< std::vector<int> > intersectEdge2;
9840   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9841   subDiv2.clear();
9842   // Step 3: compute splitMesh1D
9843   MCAuto<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9844   MCAuto<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9845   MCAuto<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9846       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9847   MCAuto<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9848   MCAuto<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9849   // deal with cells in mesh2D that are not cut but only some of their edges are
9850   MCAuto<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCopy());
9851   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9852   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9853   MCAuto<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
9854   if(!idsInDesc2DToBeRefined->empty())
9855     {
9856       DataArrayInt *out0(0),*outi0(0);
9857       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9858       MCAuto<DataArrayInt> outi0s(outi0);
9859       out0s=out0;
9860       out0s=out0s->buildUnique();
9861       out0s->sort(true);
9862     }
9863   //
9864   MCAuto<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9865   MCAuto<DataArrayDouble> baryRet1(ret1NonCol->computeCellCenterOfMass());
9866   MCAuto<DataArrayInt> elts,eltsIndex;
9867   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9868   MCAuto<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9869   MCAuto<DataArrayInt> eltsIndex3(eltsIndex2->findIdsEqual(1));
9870   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9871     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9872   MCAuto<DataArrayInt> cellsToBeModified(elts->buildUnique());
9873   MCAuto<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9874   if((DataArrayInt *)out0s)
9875     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9876   std::vector< MCAuto<MEDCouplingUMesh> > outMesh2DSplit;
9877   // OK all is ready to insert in ret2 mesh
9878   if(!untouchedCells->empty())
9879     {// the most easy part, cells in mesh2D not impacted at all
9880       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9881       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9882       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9883     }
9884   if((DataArrayInt *)out0s)
9885     {// here dealing with cells in out0s but not in cellsToBeModified
9886       MCAuto<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9887       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9888       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9889         {
9890           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9891           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9892         }
9893       int offset(ret2->getNumberOfTuples());
9894       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9895       MCAuto<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9896       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9897       int kk(0),*ret3ptr(partOfRet3->getPointer());
9898       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9899         {
9900           int faceId(std::abs(*it)-1);
9901           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9902             {
9903               int tmp(fewModifiedCells->findIdFirstEqual(*it2));
9904               if(tmp!=-1)
9905                 {
9906                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9907                     ret3ptr[2*kk]=tmp+offset;
9908                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9909                     ret3ptr[2*kk+1]=tmp+offset;
9910                 }
9911               else
9912                 {//the current edge is shared by a 2D cell that will be split just after
9913                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9914                     ret3ptr[2*kk]=-(*it2+1);
9915                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9916                     ret3ptr[2*kk+1]=-(*it2+1);
9917                 }
9918             }
9919         }
9920       m1Desc->setCoords(ret1->getCoords());
9921       ret1NonCol->setCoords(ret1->getCoords());
9922       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9923       if(!outMesh2DSplit.empty())
9924         {
9925           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9926           for(std::vector< MCAuto<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9927             (*itt)->setCoords(da);
9928         }
9929     }
9930   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9931   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9932     {
9933       MCAuto<DataArrayInt> idsNonColPerCell(elts->findIdsEqual(*it));
9934       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9935       MCAuto<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9936       MCAuto<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9937       MCAuto<DataArrayInt> partOfRet3;
9938       MCAuto<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9939       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9940       outMesh2DSplit.push_back(splitOfOneCell);
9941       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9942         ret2->pushBackSilent(*it);
9943     }
9944   //
9945   std::size_t nbOfMeshes(outMesh2DSplit.size());
9946   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9947   for(std::size_t i=0;i<nbOfMeshes;i++)
9948     tmp[i]=outMesh2DSplit[i];
9949   //
9950   ret1->getCoords()->setInfoOnComponents(compNames);
9951   MCAuto<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9952   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9953   ret3->rearrange(1);
9954   MCAuto<DataArrayInt> edgesToDealWith(ret3->findIdsStricltyNegative());
9955   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9956     {
9957       int old2DCellId(-ret3->getIJ(*it,0)-1);
9958       MCAuto<DataArrayInt> candidates(ret2->findIdsEqual(old2DCellId));
9959       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
9960     }
9961   ret3->changeValue(std::numeric_limits<int>::max(),-1);
9962   ret3->rearrange(2);
9963   //
9964   splitMesh1D=ret1.retn();
9965   splitMesh2D=ret2D.retn();
9966   cellIdInMesh2D=ret2.retn();
9967   cellIdInMesh1D=ret3.retn();
9968 }
9969
9970 /**
9971  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9972  * (newly created) nodes corresponding to the edge intersections.
9973  * Output params:
9974  * @param[out] cr, crI connectivity of the resulting mesh
9975  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9976  * TODO: describe input parameters
9977  */
9978 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9979                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9980                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9981                                                          const std::vector<double>& addCoords,
9982                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9983 {
9984   static const int SPACEDIM=2;
9985   const double *coo1(m1->getCoords()->getConstPointer());
9986   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9987   int offset1(m1->getNumberOfNodes());
9988   const double *coo2(m2->getCoords()->getConstPointer());
9989   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9990   int offset2(offset1+m2->getNumberOfNodes());
9991   int offset3(offset2+((int)addCoords.size())/2);
9992   MCAuto<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9993   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9994   // Here a BBTree on 2D-cells, not on segments:
9995   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9996   int ncell1(m1->getNumberOfCells());
9997   crI.push_back(0);
9998   for(int i=0;i<ncell1;i++)
9999     {
10000       std::vector<int> candidates2;
10001       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10002       std::map<INTERP_KERNEL::Node *,int> mapp;
10003       std::map<int,INTERP_KERNEL::Node *> mappRev;
10004       INTERP_KERNEL::QuadraticPolygon pol1;
10005       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
10006       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
10007       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
10008       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
10009       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
10010       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
10011           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
10012       //
10013       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
10014       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
10015       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
10016       for(it1.first();!it1.finished();it1.next())
10017         edges1.insert(it1.current()->getPtr());
10018       //
10019       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
10020       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10021       int ii=0;
10022       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10023         {
10024           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10025           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10026           // Complete mapping with elements coming from the current cell it2 in mesh2:
10027           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10028           // pol2 is the new QP in the final merged result.
10029           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10030               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10031         }
10032       ii=0;
10033       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10034         {
10035           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10036           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10037           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10038           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10039         }
10040       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10041       // by m2 but that we still want to keep in the final result.
10042       if(!edges1.empty())
10043         {
10044           try
10045           {
10046               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10047           }
10048           catch(INTERP_KERNEL::Exception& e)
10049           {
10050               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();
10051               throw INTERP_KERNEL::Exception(oss.str().c_str());
10052           }
10053         }
10054       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10055         (*it).second->decrRef();
10056     }
10057 }
10058
10059 /**
10060  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10061  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10062  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10063  * The caller is to deal with the resulting DataArrayInt.
10064  *  \throw If the coordinate array is not set.
10065  *  \throw If the nodal connectivity of the cells is not defined.
10066  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10067  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10068  *
10069  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10070  */
10071 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10072 {
10073   checkFullyDefined();
10074   if(getMeshDimension()!=1)
10075     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10076
10077   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10078   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10079   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10080   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10081   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10082   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10083   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10084   const int * dsi(_dsi->getConstPointer());
10085   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
10086   m_points=0;
10087   if (dsii->getNumberOfTuples())
10088     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10089
10090   int nc(getNumberOfCells());
10091   MCAuto<DataArrayInt> result(DataArrayInt::New());
10092   result->alloc(nc,1);
10093
10094   // set of edges not used so far
10095   std::set<int> edgeSet;
10096   for (int i=0; i<nc; edgeSet.insert(i), i++);
10097
10098   int startSeg=0;
10099   int newIdx=0;
10100   // while we have points with only one neighbor segments
10101   do
10102     {
10103       std::list<int> linePiece;
10104       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10105       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10106         {
10107           // Fill the list forward (resp. backward) from the start segment:
10108           int activeSeg = startSeg;
10109           int prevPointId = -20;
10110           int ptId;
10111           while (!edgeSet.empty())
10112             {
10113               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10114                 {
10115                   if (direction==0)
10116                     linePiece.push_back(activeSeg);
10117                   else
10118                     linePiece.push_front(activeSeg);
10119                   edgeSet.erase(activeSeg);
10120                 }
10121
10122               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10123               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10124               if (dsi[ptId] == 1) // hitting the end of the line
10125                 break;
10126               prevPointId = ptId;
10127               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10128               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10129             }
10130         }
10131       // Done, save final piece into DA:
10132       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10133       newIdx += linePiece.size();
10134
10135       // identify next valid start segment (one which is not consumed)
10136       if(!edgeSet.empty())
10137         startSeg = *(edgeSet.begin());
10138     }
10139   while (!edgeSet.empty());
10140   return result.retn();
10141 }
10142
10143 /// @cond INTERNAL
10144
10145 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10146 {
10147   MCAuto<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10148   std::map<MCAuto<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10149   if(it==m.end())
10150     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10151   int v((*it).second);
10152   if(v==forbVal0 || v==forbVal1)
10153     return ;
10154   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10155     isect.push_back(v);
10156 }
10157
10158 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10159 {
10160   int sz(c.size());
10161   if(sz<=1)
10162     return false;
10163   bool presenceOfOn(false);
10164   for(int i=0;i<sz;i++)
10165     {
10166       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10167       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10168         continue ;
10169       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10170       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10171     }
10172   return presenceOfOn;
10173 }
10174
10175 /// @endcond
10176
10177 /**
10178  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10179  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10180  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10181  * a minimal creation of new nodes is wanted.
10182  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10183  * nodes if a SEG3 is split without information of middle.
10184  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10185  * avoid to have a non conform mesh.
10186  *
10187  * \return int - the number of new nodes created (in most of cases 0).
10188  * 
10189  * \throw If \a this is not coherent.
10190  * \throw If \a this has not spaceDim equal to 2.
10191  * \throw If \a this has not meshDim equal to 2.
10192  * \throw If some subcells needed to be split are orphan.
10193  * \sa MEDCouplingUMesh::conformize2D
10194  */
10195 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10196 {
10197   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10198     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10199   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10200   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10201     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10202   if(midOpt==0 && midOptI==0)
10203     {
10204       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10205       return 0;
10206     }
10207   else if(midOpt!=0 && midOptI!=0)
10208     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10209   else
10210     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10211 }
10212
10213 /*!
10214  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10215  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10216  * 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
10217  * 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).
10218  * 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.
10219  * 
10220  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10221  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10222  *
10223  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10224  * This method expects that all nodes in \a this are not closer than \a eps.
10225  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10226  * 
10227  * \param [in] eps the relative error to detect merged edges.
10228  * \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
10229  *                           that the user is expected to deal with.
10230  *
10231  * \throw If \a this is not coherent.
10232  * \throw If \a this has not spaceDim equal to 2.
10233  * \throw If \a this has not meshDim equal to 2.
10234  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10235  */
10236 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10237 {
10238   static const int SPACEDIM=2;
10239   checkConsistencyLight();
10240   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10241     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10242   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10243   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10244   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10245   MCAuto<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10246   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10247   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10248   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10249   std::vector<double> addCoo;
10250   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10251   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10252   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10253   for(int i=0;i<nDescCell;i++)
10254     {
10255       std::vector<int> candidates;
10256       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10257       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10258         if(*it>i)
10259           {
10260             std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10261             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10262                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10263             INTERP_KERNEL::MergePoints merge;
10264             INTERP_KERNEL::QuadraticPolygon c1,c2;
10265             e1->intersectWith(e2,merge,c1,c2);
10266             e1->decrRef(); e2->decrRef();
10267             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10268               overlapEdge[i].push_back(*it);
10269             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10270               overlapEdge[*it].push_back(i);
10271           }
10272     }
10273   // splitting done. sort intersect point in intersectEdge.
10274   std::vector< std::vector<int> > middle(nDescCell);
10275   int nbOf2DCellsToBeSplit(0);
10276   bool middleNeedsToBeUsed(false);
10277   std::vector<bool> cells2DToTreat(nDescCell,false);
10278   for(int i=0;i<nDescCell;i++)
10279     {
10280       std::vector<int>& isect(intersectEdge[i]);
10281       int sz((int)isect.size());
10282       if(sz>1)
10283         {
10284           std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10285           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10286           e->sortSubNodesAbs(coords,isect);
10287           e->decrRef();
10288         }
10289       if(sz!=0)
10290         {
10291           int idx0(rdi[i]),idx1(rdi[i+1]);
10292           if(idx1-idx0!=1)
10293             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10294           if(!cells2DToTreat[rd[idx0]])
10295             {
10296               cells2DToTreat[rd[idx0]]=true;
10297               nbOf2DCellsToBeSplit++;
10298             }
10299           // try to reuse at most eventual 'middle' of SEG3
10300           std::vector<int>& mid(middle[i]);
10301           mid.resize(sz+1,-1);
10302           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10303             {
10304               middleNeedsToBeUsed=true;
10305               const std::vector<int>& candidates(overlapEdge[i]);
10306               std::vector<int> trueCandidates;
10307               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10308                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10309                   trueCandidates.push_back(*itc);
10310               int stNode(c[ci[i]+1]),endNode(isect[0]);
10311               for(int j=0;j<sz+1;j++)
10312                 {
10313                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10314                     {
10315                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10316                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10317                         { mid[j]=*itc; break; }
10318                     }
10319                   stNode=endNode;
10320                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10321                 }
10322             }
10323         }
10324     }
10325   MCAuto<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10326   if(nbOf2DCellsToBeSplit==0)
10327     return ret.retn();
10328   //
10329   int *retPtr(ret->getPointer());
10330   for(int i=0;i<nCell;i++)
10331     if(cells2DToTreat[i])
10332       *retPtr++=i;
10333   //
10334   MCAuto<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10335   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10336   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10337   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10338   if(middleNeedsToBeUsed)
10339     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10340   MCAuto<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10341   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10342   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.
10343   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10344   {
10345     bool areNodesMerged; int newNbOfNodes;
10346     if(nbOfNodesCreated!=0)
10347       MCAuto<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10348   }
10349   return ret.retn();
10350 }
10351
10352 /*!
10353  * 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.
10354  * 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).
10355  * 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
10356  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10357  * 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
10358  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10359  *
10360  * 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
10361  * using new instance, idem for coordinates.
10362  *
10363  * 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.
10364  * 
10365  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10366  *
10367  * \throw If \a this is not coherent.
10368  * \throw If \a this has not spaceDim equal to 2.
10369  * \throw If \a this has not meshDim equal to 2.
10370  * 
10371  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10372  */
10373 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10374 {
10375   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10376   checkConsistencyLight();
10377   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10378     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10379   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10380   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10381   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10382   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10383   MCAuto<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10384   MCAuto<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10385   const double *coords(_coords->begin());
10386   int *newciptr(newci->getPointer());
10387   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10388     {
10389       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10390         ret->pushBackSilent(i);
10391       newciptr[1]=newc->getNumberOfTuples();
10392     }
10393   //
10394   if(ret->empty())
10395     return ret.retn();
10396   if(!appendedCoords->empty())
10397     {
10398       appendedCoords->rearrange(2);
10399       MCAuto<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10400       //non const part
10401       setCoords(newCoords);
10402     }
10403   //non const part
10404   setConnectivity(newc,newci,true);
10405   return ret.retn();
10406 }
10407
10408 /*!
10409  * \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.
10410  *                               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.
10411  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10412  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10413  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10414  * \param [out] addCoo - nodes to be append at the end
10415  * \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.
10416  */
10417 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10418                                          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)
10419 {
10420   static const int SPACEDIM=2;
10421   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10422   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10423   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10424   // Build BB tree of all edges in the tool mesh (second mesh)
10425   MCAuto<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10426   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10427   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10428   intersectEdge1.resize(nDescCell1);
10429   colinear2.resize(nDescCell2);
10430   subDiv2.resize(nDescCell2);
10431   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10432
10433   std::vector<int> candidates1(1);
10434   int offset1(m1Desc->getNumberOfNodes());
10435   int offset2(offset1+m2Desc->getNumberOfNodes());
10436   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10437     {
10438       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10439       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10440       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10441         {
10442           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10443           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10444           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10445           candidates1[0]=i;
10446           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10447           // 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
10448           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10449           std::set<INTERP_KERNEL::Node *> nodes;
10450           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10451           std::size_t szz(nodes.size());
10452           std::vector< MCAuto<INTERP_KERNEL::Node> > nodesSafe(szz);
10453           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10454           for(std::size_t iii=0;iii<szz;iii++,itt++)
10455             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10456           // end of protection
10457           // Performs egde cutting:
10458           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10459           delete pol2;
10460           delete pol1;
10461         }
10462       else
10463         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10464         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10465     }
10466 }
10467
10468 /*!
10469  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10470  * It builds the descending connectivity of the two meshes, and then using a binary tree
10471  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10472  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10473  */
10474 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10475                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10476                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10477                                                    std::vector<double>& addCoo,
10478                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10479 {
10480   // Build desc connectivity
10481   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10482   desc2=DataArrayInt::New();
10483   descIndx2=DataArrayInt::New();
10484   revDesc2=DataArrayInt::New();
10485   revDescIndx2=DataArrayInt::New();
10486   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10487   MCAuto<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10488   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10489   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10490   MCAuto<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10491   std::map<int,int> notUsedMap;
10492   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10493   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10494   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10495 }
10496
10497 /*!
10498  * This method performs the 2nd step of Partition of 2D mesh.
10499  * This method has 4 inputs :
10500  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10501  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10502  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10503  * 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'
10504  * Nodes end up lying consecutively on a cutted edge.
10505  * \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.
10506  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10507  * \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.
10508  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10509  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10510  */
10511 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10512                                            const std::vector<double>& addCoo,
10513                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10514 {
10515   int offset1=m1->getNumberOfNodes();
10516   int ncell=m2->getNumberOfCells();
10517   const int *c=m2->getNodalConnectivity()->getConstPointer();
10518   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10519   const double *coo=m2->getCoords()->getConstPointer();
10520   const double *cooBis=m1->getCoords()->getConstPointer();
10521   int offset2=offset1+m2->getNumberOfNodes();
10522   intersectEdge.resize(ncell);
10523   for(int i=0;i<ncell;i++,cI++)
10524     {
10525       const std::vector<int>& divs=subDiv[i];
10526       int nnode=cI[1]-cI[0]-1;
10527       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10528       std::map<INTERP_KERNEL::Node *, int> mapp22;
10529       for(int j=0;j<nnode;j++)
10530         {
10531           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10532           int nnid=c[(*cI)+j+1];
10533           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10534           mapp22[nn]=nnid+offset1;
10535         }
10536       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10537       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10538         ((*it).second.first)->decrRef();
10539       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10540       std::map<INTERP_KERNEL::Node *,int> mapp3;
10541       for(std::size_t j=0;j<divs.size();j++)
10542         {
10543           int id=divs[j];
10544           INTERP_KERNEL::Node *tmp=0;
10545           if(id<offset1)
10546             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10547           else if(id<offset2)
10548             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10549           else
10550             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10551           addNodes[j]=tmp;
10552           mapp3[tmp]=id;
10553         }
10554       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10555       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10556         (*it)->decrRef();
10557       e->decrRef();
10558     }
10559 }
10560
10561 /*!
10562  * 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).
10563  * 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
10564  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10565  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10566  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10567  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10568  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10569  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10570  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10571  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10572  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10573  * \param [out] cut3DSuf input/output param.
10574  */
10575 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10576                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10577                                                    const int *desc, const int *descIndx, 
10578                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10579 {
10580   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10581   int nbOf3DSurfCell=(int)cut3DSurf.size();
10582   for(int i=0;i<nbOf3DSurfCell;i++)
10583     {
10584       std::vector<int> res;
10585       int offset=descIndx[i];
10586       int nbOfSeg=descIndx[i+1]-offset;
10587       for(int j=0;j<nbOfSeg;j++)
10588         {
10589           int edgeId=desc[offset+j];
10590           int status=cut3DCurve[edgeId];
10591           if(status!=-2)
10592             {
10593               if(status>-1)
10594                 res.push_back(status);
10595               else
10596                 {
10597                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10598                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10599                 }
10600             }
10601         }
10602       switch(res.size())
10603       {
10604         case 2:
10605           {
10606             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10607             break;
10608           }
10609         case 1:
10610         case 0:
10611           {
10612             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10613             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10614             if(res.size()==2)
10615               {
10616                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10617               }
10618             else
10619               {
10620                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10621               }
10622             break;
10623           }
10624         default:
10625           {// case when plane is on a multi colinear edge of a polyhedron
10626             if((int)res.size()==2*nbOfSeg)
10627               {
10628                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10629               }
10630             else
10631               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10632           }
10633       }
10634     }
10635 }
10636
10637 /*!
10638  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10639  * 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).
10640  * 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
10641  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10642  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10643  * \param desc is the descending connectivity 3D->3DSurf
10644  * \param descIndx is the descending connectivity index 3D->3DSurf
10645  */
10646 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10647                                                   const int *desc, const int *descIndx,
10648                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10649 {
10650   checkFullyDefined();
10651   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10652     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10653   const int *nodal3D=_nodal_connec->getConstPointer();
10654   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10655   int nbOfCells=getNumberOfCells();
10656   for(int i=0;i<nbOfCells;i++)
10657     {
10658       std::map<int, std::set<int> > m;
10659       int offset=descIndx[i];
10660       int nbOfFaces=descIndx[i+1]-offset;
10661       int start=-1;
10662       int end=-1;
10663       for(int j=0;j<nbOfFaces;j++)
10664         {
10665           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10666           if(p.first!=-1 && p.second!=-1)
10667             {
10668               if(p.first!=-2)
10669                 {
10670                   start=p.first; end=p.second;
10671                   m[p.first].insert(p.second);
10672                   m[p.second].insert(p.first);
10673                 }
10674               else
10675                 {
10676                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10677                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10678                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10679                   INTERP_KERNEL::NormalizedCellType cmsId;
10680                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10681                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10682                   for(unsigned k=0;k<nbOfNodesSon;k++)
10683                     {
10684                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10685                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10686                     }
10687                 }
10688             }
10689         }
10690       if(m.empty())
10691         continue;
10692       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10693       int prev=end;
10694       while(end!=start)
10695         {
10696           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10697           const std::set<int>& s=(*it).second;
10698           std::set<int> s2; s2.insert(prev);
10699           std::set<int> s3;
10700           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10701           if(s3.size()==1)
10702             {
10703               int val=*s3.begin();
10704               conn.push_back(start);
10705               prev=start;
10706               start=val;
10707             }
10708           else
10709             start=end;
10710         }
10711       conn.push_back(end);
10712       if(conn.size()>3)
10713         {
10714           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10715           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10716           cellIds->pushBackSilent(i);
10717         }
10718     }
10719 }
10720
10721 /*!
10722  * 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
10723  * 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
10724  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10725  * 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
10726  * 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.
10727  * 
10728  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10729  */
10730 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10731 {
10732   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10733   if(sz>=4)
10734     {
10735       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10736       if(cm.getDimension()==2)
10737         {
10738           const int *node=nodalConnBg+1;
10739           int startNode=*node++;
10740           double refX=coords[2*startNode];
10741           for(;node!=nodalConnEnd;node++)
10742             {
10743               if(coords[2*(*node)]<refX)
10744                 {
10745                   startNode=*node;
10746                   refX=coords[2*startNode];
10747                 }
10748             }
10749           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10750           refX=1e300;
10751           double tmp1;
10752           double tmp2[2];
10753           double angle0=-M_PI/2;
10754           //
10755           int nextNode=-1;
10756           int prevNode=-1;
10757           double resRef;
10758           double angleNext=0.;
10759           while(nextNode!=startNode)
10760             {
10761               nextNode=-1;
10762               resRef=1e300;
10763               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10764                 {
10765                   if(*node!=tmpOut.back() && *node!=prevNode)
10766                     {
10767                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10768                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10769                       double res;
10770                       if(angleM<=angle0)
10771                         res=angle0-angleM;
10772                       else
10773                         res=angle0-angleM+2.*M_PI;
10774                       if(res<resRef)
10775                         {
10776                           nextNode=*node;
10777                           resRef=res;
10778                           angleNext=angleM;
10779                         }
10780                     }
10781                 }
10782               if(nextNode!=startNode)
10783                 {
10784                   angle0=angleNext-M_PI;
10785                   if(angle0<-M_PI)
10786                     angle0+=2*M_PI;
10787                   prevNode=tmpOut.back();
10788                   tmpOut.push_back(nextNode);
10789                 }
10790             }
10791           std::vector<int> tmp3(2*(sz-1));
10792           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10793           std::copy(nodalConnBg+1,nodalConnEnd,it);
10794           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10795             {
10796               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10797               return false;
10798             }
10799           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10800             {
10801               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10802               return false;
10803             }
10804           else
10805             {
10806               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10807               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10808               return true;
10809             }
10810         }
10811       else
10812         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10813     }
10814   else
10815     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10816 }
10817
10818 /*!
10819  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10820  * 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.
10821  * 
10822  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10823  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10824  * \param [in,out] arr array in which the remove operation will be done.
10825  * \param [in,out] arrIndx array in the remove operation will modify
10826  * \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])
10827  * \return true if \b arr and \b arrIndx have been modified, false if not.
10828  */
10829 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10830 {
10831   if(!arrIndx || !arr)
10832     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10833   if(offsetForRemoval<0)
10834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10835   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10836   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10837   int *arrIPtr=arrIndx->getPointer();
10838   *arrIPtr++=0;
10839   int previousArrI=0;
10840   const int *arrPtr=arr->getConstPointer();
10841   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10842   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10843     {
10844       if(*arrIPtr-previousArrI>offsetForRemoval)
10845         {
10846           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10847             {
10848               if(s.find(*work)==s.end())
10849                 arrOut.push_back(*work);
10850             }
10851         }
10852       previousArrI=*arrIPtr;
10853       *arrIPtr=(int)arrOut.size();
10854     }
10855   if(arr->getNumberOfTuples()==(int)arrOut.size())
10856     return false;
10857   arr->alloc((int)arrOut.size(),1);
10858   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10859   return true;
10860 }
10861
10862 /*!
10863  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10864  * (\ref numbering-indirect).
10865  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10866  * The selection of extraction is done standardly in new2old format.
10867  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10868  *
10869  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10870  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10871  * \param [in] arrIn arr origin array from which the extraction will be done.
10872  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10873  * \param [out] arrOut the resulting array
10874  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10875  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
10876  */
10877 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10878                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10879 {
10880   if(!arrIn || !arrIndxIn)
10881     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10882   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10883   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10884     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10885   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10886   const int *arrInPtr=arrIn->getConstPointer();
10887   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10888   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10889   if(nbOfGrps<0)
10890     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10891   int maxSizeOfArr=arrIn->getNumberOfTuples();
10892   MCAuto<DataArrayInt> arro=DataArrayInt::New();
10893   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
10894   arrIo->alloc((int)(sz+1),1);
10895   const int *idsIt=idsOfSelectBg;
10896   int *work=arrIo->getPointer();
10897   *work++=0;
10898   int lgth=0;
10899   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10900     {
10901       if(*idsIt>=0 && *idsIt<nbOfGrps)
10902         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10903       else
10904         {
10905           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10906           throw INTERP_KERNEL::Exception(oss.str().c_str());
10907         }
10908       if(lgth>=work[-1])
10909         *work=lgth;
10910       else
10911         {
10912           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10913           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10914           throw INTERP_KERNEL::Exception(oss.str().c_str());
10915         }
10916     }
10917   arro->alloc(lgth,1);
10918   work=arro->getPointer();
10919   idsIt=idsOfSelectBg;
10920   for(std::size_t i=0;i<sz;i++,idsIt++)
10921     {
10922       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10923         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10924       else
10925         {
10926           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10927           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10928           throw INTERP_KERNEL::Exception(oss.str().c_str());
10929         }
10930     }
10931   arrOut=arro.retn();
10932   arrIndexOut=arrIo.retn();
10933 }
10934
10935 /*!
10936  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10937  * (\ref numbering-indirect).
10938  * 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 ).
10939  * The selection of extraction is done standardly in new2old format.
10940  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10941  *
10942  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
10943  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
10944  * \param [in] idsOfSelectStep
10945  * \param [in] arrIn arr origin array from which the extraction will be done.
10946  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10947  * \param [out] arrOut the resulting array
10948  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10949  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10950  */
10951 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10952                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10953 {
10954   if(!arrIn || !arrIndxIn)
10955     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
10956   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10957   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10958     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
10959   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
10960   const int *arrInPtr=arrIn->getConstPointer();
10961   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10962   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10963   if(nbOfGrps<0)
10964     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10965   int maxSizeOfArr=arrIn->getNumberOfTuples();
10966   MCAuto<DataArrayInt> arro=DataArrayInt::New();
10967   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
10968   arrIo->alloc((int)(sz+1),1);
10969   int idsIt=idsOfSelectStart;
10970   int *work=arrIo->getPointer();
10971   *work++=0;
10972   int lgth=0;
10973   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10974     {
10975       if(idsIt>=0 && idsIt<nbOfGrps)
10976         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10977       else
10978         {
10979           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10980           throw INTERP_KERNEL::Exception(oss.str().c_str());
10981         }
10982       if(lgth>=work[-1])
10983         *work=lgth;
10984       else
10985         {
10986           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10987           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10988           throw INTERP_KERNEL::Exception(oss.str().c_str());
10989         }
10990     }
10991   arro->alloc(lgth,1);
10992   work=arro->getPointer();
10993   idsIt=idsOfSelectStart;
10994   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10995     {
10996       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10997         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10998       else
10999         {
11000           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
11001           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
11002           throw INTERP_KERNEL::Exception(oss.str().c_str());
11003         }
11004     }
11005   arrOut=arro.retn();
11006   arrIndexOut=arrIo.retn();
11007 }
11008
11009 /*!
11010  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11011  * 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
11012  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11013  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11014  *
11015  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11016  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11017  * \param [in] arrIn arr origin array from which the extraction will be done.
11018  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11019  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
11020  * \param [in] srcArrIndex index array of \b srcArr
11021  * \param [out] arrOut the resulting array
11022  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11023  * 
11024  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11025  */
11026 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11027                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11028                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11029 {
11030   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11031     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11032   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11033   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11034   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11035   std::vector<bool> v(nbOfTuples,true);
11036   int offset=0;
11037   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11038   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11039   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11040     {
11041       if(*it>=0 && *it<nbOfTuples)
11042         {
11043           v[*it]=false;
11044           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11045         }
11046       else
11047         {
11048           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11049           throw INTERP_KERNEL::Exception(oss.str().c_str());
11050         }
11051     }
11052   srcArrIndexPtr=srcArrIndex->getConstPointer();
11053   arrIo->alloc(nbOfTuples+1,1);
11054   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11055   const int *arrInPtr=arrIn->getConstPointer();
11056   const int *srcArrPtr=srcArr->getConstPointer();
11057   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11058   int *arroPtr=arro->getPointer();
11059   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11060     {
11061       if(v[ii])
11062         {
11063           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11064           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11065         }
11066       else
11067         {
11068           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11069           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11070           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11071         }
11072     }
11073   arrOut=arro.retn();
11074   arrIndexOut=arrIo.retn();
11075 }
11076
11077 /*!
11078  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11079  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11080  *
11081  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11082  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11083  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11084  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11085  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11086  * \param [in] srcArrIndex index array of \b srcArr
11087  * 
11088  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11089  */
11090 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11091                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11092 {
11093   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11094     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11095   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11096   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11097   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11098   int *arrInOutPtr=arrInOut->getPointer();
11099   const int *srcArrPtr=srcArr->getConstPointer();
11100   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11101     {
11102       if(*it>=0 && *it<nbOfTuples)
11103         {
11104           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11105             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11106           else
11107             {
11108               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] !";
11109               throw INTERP_KERNEL::Exception(oss.str().c_str());
11110             }
11111         }
11112       else
11113         {
11114           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11115           throw INTERP_KERNEL::Exception(oss.str().c_str());
11116         }
11117     }
11118 }
11119
11120 /*!
11121  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11122  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11123  * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 looking at arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
11124  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11125  * A negative value in \b arrIn means that it is ignored.
11126  * 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.
11127  * 
11128  * \param [in] arrIn arr origin array from which the extraction will be done.
11129  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11130  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11131  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11132  */
11133 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11134 {
11135   int seed=0,nbOfDepthPeelingPerformed=0;
11136   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11137 }
11138
11139 /*!
11140  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11141  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11142  * 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]].
11143  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11144  * A negative value in \b arrIn means that it is ignored.
11145  * 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.
11146  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11147  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11148  * \param [in] arrIn arr origin array from which the extraction will be done.
11149  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11150  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11151  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11152  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11153  * \sa MEDCouplingUMesh::partitionBySpreadZone
11154  */
11155 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11156 {
11157   nbOfDepthPeelingPerformed=0;
11158   if(!arrIndxIn)
11159     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11160   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11161   if(nbOfTuples<=0)
11162     {
11163       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11164       return ret;
11165     }
11166   //
11167   std::vector<bool> fetched(nbOfTuples,false);
11168   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11169 }
11170
11171 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11172 {
11173   nbOfDepthPeelingPerformed=0;
11174   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11175     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11176   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11177   std::vector<bool> fetched2(nbOfTuples,false);
11178   int i=0;
11179   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11180     {
11181       if(*seedElt>=0 && *seedElt<nbOfTuples)
11182         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11183       else
11184         { 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()); }
11185     }
11186   const int *arrInPtr=arrIn->getConstPointer();
11187   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11188   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11189   std::vector<int> idsToFetch1(seedBg,seedEnd);
11190   std::vector<int> idsToFetch2;
11191   std::vector<int> *idsToFetch=&idsToFetch1;
11192   std::vector<int> *idsToFetchOther=&idsToFetch2;
11193   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11194     {
11195       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11196         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11197           if(!fetched[*it2])
11198             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11199       std::swap(idsToFetch,idsToFetchOther);
11200       idsToFetchOther->clear();
11201       nbOfDepthPeelingPerformed++;
11202     }
11203   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11204   i=0;
11205   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11206   int *retPtr=ret->getPointer();
11207   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11208     if(*it)
11209       *retPtr++=i;
11210   return ret.retn();
11211 }
11212
11213 /*!
11214  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11215  * 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
11216  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11217  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11218  *
11219  * \param [in] start begin of set of ids of the input extraction (included)
11220  * \param [in] end end of set of ids of the input extraction (excluded)
11221  * \param [in] step step of the set of ids in range mode.
11222  * \param [in] arrIn arr origin array from which the extraction will be done.
11223  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11224  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11225  * \param [in] srcArrIndex index array of \b srcArr
11226  * \param [out] arrOut the resulting array
11227  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11228  * 
11229  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11230  */
11231 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11232                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11233                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11234 {
11235   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11236     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
11237   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11238   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11239   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11240   int offset=0;
11241   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11242   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11243   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
11244   int it=start;
11245   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11246     {
11247       if(it>=0 && it<nbOfTuples)
11248         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11249       else
11250         {
11251           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11252           throw INTERP_KERNEL::Exception(oss.str().c_str());
11253         }
11254     }
11255   srcArrIndexPtr=srcArrIndex->getConstPointer();
11256   arrIo->alloc(nbOfTuples+1,1);
11257   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11258   const int *arrInPtr=arrIn->getConstPointer();
11259   const int *srcArrPtr=srcArr->getConstPointer();
11260   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11261   int *arroPtr=arro->getPointer();
11262   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11263     {
11264       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11265       if(pos<0)
11266         {
11267           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11268           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11269         }
11270       else
11271         {
11272           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11273           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11274         }
11275     }
11276   arrOut=arro.retn();
11277   arrIndexOut=arrIo.retn();
11278 }
11279
11280 /*!
11281  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11282  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11283  *
11284  * \param [in] start begin of set of ids of the input extraction (included)
11285  * \param [in] end end of set of ids of the input extraction (excluded)
11286  * \param [in] step step of the set of ids in range mode.
11287  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11288  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11289  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11290  * \param [in] srcArrIndex index array of \b srcArr
11291  * 
11292  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11293  */
11294 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11295                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11296 {
11297   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11298     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
11299   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11300   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11301   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11302   int *arrInOutPtr=arrInOut->getPointer();
11303   const int *srcArrPtr=srcArr->getConstPointer();
11304   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
11305   int it=start;
11306   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11307     {
11308       if(it>=0 && it<nbOfTuples)
11309         {
11310           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11311             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11312           else
11313             {
11314               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11315               throw INTERP_KERNEL::Exception(oss.str().c_str());
11316             }
11317         }
11318       else
11319         {
11320           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11321           throw INTERP_KERNEL::Exception(oss.str().c_str());
11322         }
11323     }
11324 }
11325
11326 /*!
11327  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11328  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11329  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11330  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11331  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11332  * 
11333  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11334  */
11335 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11336 {
11337   checkFullyDefined();
11338   int mdim=getMeshDimension();
11339   int spaceDim=getSpaceDimension();
11340   if(mdim!=spaceDim)
11341     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11342   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11343   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11344   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
11345   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11346   ret->setCoords(getCoords());
11347   ret->allocateCells((int)partition.size());
11348   //
11349   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11350     {
11351       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11352       MCAuto<DataArrayInt> cell;
11353       switch(mdim)
11354       {
11355         case 2:
11356           cell=tmp->buildUnionOf2DMesh();
11357           break;
11358         case 3:
11359           cell=tmp->buildUnionOf3DMesh();
11360           break;
11361         default:
11362           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11363       }
11364
11365       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11366     }
11367   //
11368   ret->finishInsertingCells();
11369   return ret.retn();
11370 }
11371
11372 /*!
11373  * This method partitions \b this into contiguous zone.
11374  * This method only needs a well defined connectivity. Coordinates are not considered here.
11375  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11376  */
11377 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11378 {
11379   int nbOfCellsCur=getNumberOfCells();
11380   std::vector<DataArrayInt *> ret;
11381   if(nbOfCellsCur<=0)
11382     return ret;
11383   DataArrayInt *neigh=0,*neighI=0;
11384   computeNeighborsOfCells(neigh,neighI);
11385   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11386   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11387   std::vector< MCAuto<DataArrayInt> > ret2;
11388   int seed=0;
11389   while(seed<nbOfCellsCur)
11390     {
11391       int nbOfPeelPerformed=0;
11392       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11393       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11394     }
11395   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11396     ret.push_back((*it).retn());
11397   return ret;
11398 }
11399
11400 /*!
11401  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11402  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11403  *
11404  * \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.
11405  * \return a newly allocated DataArrayInt to be managed by the caller.
11406  * \throw In case of \a code has not the right format (typically of size 3*n)
11407  */
11408 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11409 {
11410   MCAuto<DataArrayInt> ret=DataArrayInt::New();
11411   std::size_t nb=code.size()/3;
11412   if(code.size()%3!=0)
11413     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11414   ret->alloc((int)nb,2);
11415   int *retPtr=ret->getPointer();
11416   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11417     {
11418       retPtr[0]=code[3*i+2];
11419       retPtr[1]=code[3*i+2]+code[3*i+1];
11420     }
11421   return ret.retn();
11422 }
11423
11424 /*!
11425  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11426  * All cells in \a this are expected to be linear 3D cells.
11427  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11428  * It leads to an increase to number of cells.
11429  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11430  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11431  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11432  *
11433  * \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.
11434  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11435  * \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. 
11436  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11437  *          an id of old cell producing it. The caller is to delete this array using
11438  *         decrRef() as it is no more needed.
11439  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11440  *
11441  * \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
11442  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11443  * 
11444  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11445  * \throw If \a this is not fully constituted with linear 3D cells.
11446  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11447  */
11448 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11449 {
11450   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11451   checkConnectivityFullyDefined();
11452   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11453     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11454   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11455   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11456   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11457   int *retPt(ret->getPointer());
11458   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11459   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11460   const int *oldc(_nodal_connec->begin());
11461   const int *oldci(_nodal_connec_index->begin());
11462   const double *coords(_coords->begin());
11463   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11464     {
11465       std::vector<int> a; std::vector<double> b;
11466       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11467       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11468       const int *aa(&a[0]);
11469       if(!b.empty())
11470         {
11471           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11472             if(*it<0)
11473               *it=(-(*(it))-1+nbNodes);
11474           addPts->insertAtTheEnd(b.begin(),b.end());
11475           nbNodes+=(int)b.size()/3;
11476         }
11477       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11478         newConn->insertAtTheEnd(aa,aa+4);
11479     }
11480   if(!addPts->empty())
11481     {
11482       addPts->rearrange(3);
11483       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11484       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11485       ret0->setCoords(addPts);
11486     }
11487   else
11488     {
11489       nbOfAdditionalPoints=0;
11490       ret0->setCoords(getCoords());
11491     }
11492   ret0->setNodalConnectivity(newConn);
11493   //
11494   ret->computeOffsetsFull();
11495   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11496   return ret0.retn();
11497 }
11498
11499 /*!
11500  * 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). 
11501  *
11502  * \sa MEDCouplingUMesh::split2DCells
11503  */
11504 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11505 {
11506   checkConnectivityFullyDefined();
11507   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+subNodesInSeg->getNumberOfTuples());
11508   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11509   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11510   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11511   int prevPosOfCi(ciPtr[0]);
11512   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11513     {
11514       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11515       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11516       for(int j=0;j<sz;j++)
11517         {
11518           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11519           for(int k=0;k<sz2;k++)
11520             *cPtr++=subPtr[offset2+k];
11521           if(j!=sz-1)
11522             *cPtr++=oldConn[prevPosOfCi+j+2];
11523           deltaSz+=sz2;
11524         }
11525       prevPosOfCi=ciPtr[1];
11526       ciPtr[1]=ciPtr[0]+1+sz+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::split2DCellsLinear : Some of edges to be split are orphan !");
11530   _nodal_connec->decrRef();
11531   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11532 }
11533
11534 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11535 {
11536   if(id!=-1)
11537     return id;
11538   else
11539     {
11540       int ret(nodesCnter++);
11541       double newPt[2];
11542       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11543       addCoo.insertAtTheEnd(newPt,newPt+2);
11544       return ret;
11545     }
11546 }
11547
11548 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11549 {
11550   if(id!=-1)
11551     return id;
11552   else
11553     {
11554       int ret(nodesCnter++);
11555       double newPt[2];
11556       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11557       addCoo.insertAtTheEnd(newPt,newPt+2);
11558       return ret;
11559     }
11560 }
11561
11562
11563 /// @cond INTERNAL
11564
11565 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)
11566 {
11567   int tmp[3];
11568   int trueStart(start>=0?start:nbOfEdges+start);
11569   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11570   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11571   if(linOrArc)
11572     {
11573       if(stp-start>1)
11574         {
11575           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11576           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11577           middles.push_back(tmp3+offset);
11578         }
11579       else
11580         middles.push_back(connBg[trueStart+nbOfEdges]);
11581     }
11582 }
11583
11584 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)
11585 {
11586   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11587   newConnOfCell->pushBackSilent(tmpEnd);
11588   if(linOrArc)
11589     {
11590       if(stp-start>1)
11591         {
11592           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11593           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11594           middles.push_back(tmp3+offset);
11595         }
11596       else
11597         middles.push_back(connBg[start+nbOfEdges]);
11598     }
11599 }
11600
11601 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)
11602 {
11603   // only the quadratic point to deal with:
11604   if(linOrArc)
11605     {
11606       if(stp-start>1)
11607         {
11608           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11609           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11610           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11611           middles.push_back(tmp3+offset);
11612         }
11613       else
11614         middles.push_back(connBg[start+nbOfEdges]);
11615     }
11616 }
11617
11618 /// @endcond
11619
11620 /*!
11621  * 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 ) .
11622  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11623  */
11624 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11625 {
11626   std::size_t sz(std::distance(connBg,connEnd));
11627   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11628     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11629   sz--;
11630   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11631   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11632   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11633   unsigned nbOfHit(0); // number of fusions operated
11634   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11635   const unsigned int maxNbOfHit = cm.isQuadratic() ? nbs-2 : nbs-3;  // a quad cell is authorized to end up with only two edges, a linear one has to keep 3 at least
11636   INTERP_KERNEL::NormalizedCellType typeOfSon;
11637   std::vector<int> middles;
11638   bool ret(false);
11639   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11640     {
11641       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11642       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
11643       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11644       posEndElt = posBaseElt+1;
11645
11646       // Look backward first: are the final edges of the cells colinear with the first ones?
11647       // This initializes posBaseElt.
11648       if(nbOfTurn==0)
11649         {
11650           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11651             {
11652               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11653               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11654               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11655               bool isColinear=eint->areColinears();
11656               if(isColinear)
11657                 {
11658                   nbOfHit++;
11659                   posBaseElt--;
11660                   ret=true;
11661                 }
11662               delete eint;
11663               eCand->decrRef();
11664               if(!isColinear)
11665                 break;
11666             }
11667         }
11668       // Now move forward:
11669       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11670       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11671         {
11672           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11673           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11674           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11675           bool isColinear(eint->areColinears());
11676           if(isColinear)
11677             {
11678               nbOfHit++;
11679               posEndElt++;
11680               ret=true;
11681             }
11682           delete eint;
11683           eCand->decrRef();
11684           if(!isColinear)
11685               break;
11686         }
11687       //push [posBaseElt,posEndElt) in newConnOfCell using e
11688       // The if clauses below are (volontary) not mutually exclusive: on a quad cell with 2 edges, the end of the connectivity is also its begining!
11689       if(nbOfTurn==0)
11690         // at the begining of the connectivity (insert type)
11691         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11692       else if((nbOfHit+nbOfTurn) != (nbs-1))
11693         // in the middle
11694         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11695       if ((nbOfHit+nbOfTurn) == (nbs-1))
11696         // at the end (only quad points to deal with)
11697         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11698       posBaseElt=posEndElt;
11699       e->decrRef();
11700     }
11701   if(!middles.empty())
11702     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11703   return ret;
11704 }
11705
11706 /*!
11707  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11708  *
11709  * \return  int - the number of new nodes created.
11710  * \sa MEDCouplingUMesh::split2DCells
11711  */
11712 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11713 {
11714   checkConsistencyLight();
11715   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11716   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11717   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11718   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11719   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11720   const double *oldCoordsPtr(getCoords()->begin());
11721   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11722   int prevPosOfCi(ciPtr[0]);
11723   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11724     {
11725       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11726       for(int j=0;j<sz;j++)
11727         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11728       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11729       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11730         {
11731           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11732           if(sz2==0)
11733             {
11734               if(j<sz-1)
11735                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11736               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11737               continue;
11738             }
11739           std::vector<INTERP_KERNEL::Node *> ns(3);
11740           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11741           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11742           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11743           MCAuto<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11744           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11745             {
11746               cPtr[1]=subPtr[offset2+k];
11747               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11748             }
11749           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11750           if(j!=sz-1)
11751             { cPtr[1]=tmpEnd; }
11752           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11753         }
11754       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11755       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11756     }
11757   if(c->end()!=cPtr)
11758     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11759   _nodal_connec->decrRef();
11760   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11761   addCoo->rearrange(2);
11762   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11763   setCoords(coo);
11764   return addCoo->getNumberOfTuples();
11765 }
11766
11767 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11768 {
11769   if(nodalConnec && nodalConnecIndex)
11770     {
11771       types.clear();
11772       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11773       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11774       if(nbOfElem>0)
11775         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11776           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11777     }
11778 }
11779
11780 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11781     _own_cell(true),_cell_id(-1),_nb_cell(0)
11782 {
11783   if(mesh)
11784     {
11785       mesh->incrRef();
11786       _nb_cell=mesh->getNumberOfCells();
11787     }
11788 }
11789
11790 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11791 {
11792   if(_mesh)
11793     _mesh->decrRef();
11794   if(_own_cell)
11795     delete _cell;
11796 }
11797
11798 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11799     _own_cell(false),_cell_id(bg-1),
11800     _nb_cell(end)
11801 {
11802   if(mesh)
11803     mesh->incrRef();
11804 }
11805
11806 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11807 {
11808   _cell_id++;
11809   if(_cell_id<_nb_cell)
11810     {
11811       _cell->next();
11812       return _cell;
11813     }
11814   else
11815     return 0;
11816 }
11817
11818 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11819 {
11820   if(_mesh)
11821     _mesh->incrRef();
11822 }
11823
11824 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11825 {
11826   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11827 }
11828
11829 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11830 {
11831   if(_mesh)
11832     _mesh->decrRef();
11833 }
11834
11835 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11836     _itc(itc),
11837     _bg(bg),_end(end)
11838 {
11839   if(_mesh)
11840     _mesh->incrRef();
11841 }
11842
11843 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11844 {
11845   if(_mesh)
11846     _mesh->decrRef();
11847 }
11848
11849 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11850 {
11851   return _type;
11852 }
11853
11854 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11855 {
11856   return _end-_bg;
11857 }
11858
11859 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11860 {
11861   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11862 }
11863
11864 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11865 {
11866   if(mesh)
11867     {
11868       mesh->incrRef();
11869       _nb_cell=mesh->getNumberOfCells();
11870     }
11871 }
11872
11873 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11874 {
11875   if(_mesh)
11876     _mesh->decrRef();
11877   delete _cell;
11878 }
11879
11880 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11881 {
11882   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11883   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11884   if(_cell_id<_nb_cell)
11885     {
11886       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11887       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
11888       int startId=_cell_id;
11889       _cell_id+=nbOfElems;
11890       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11891     }
11892   else
11893     return 0;
11894 }
11895
11896 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11897 {
11898   if(mesh)
11899     {
11900       _conn=mesh->getNodalConnectivity()->getPointer();
11901       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11902     }
11903 }
11904
11905 void MEDCouplingUMeshCell::next()
11906 {
11907   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11908     {
11909       _conn+=_conn_lgth;
11910       _conn_indx++;
11911     }
11912   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11913 }
11914
11915 std::string MEDCouplingUMeshCell::repr() const
11916 {
11917   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11918     {
11919       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11920       oss << " : ";
11921       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11922       return oss.str();
11923     }
11924   else
11925     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11926 }
11927
11928 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11929 {
11930   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11931     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11932   else
11933     return INTERP_KERNEL::NORM_ERROR;
11934 }
11935
11936 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11937 {
11938   lgth=_conn_lgth;
11939   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11940     return _conn;
11941   else
11942     return 0;
11943 }