Salome HOME
Merge 'agy/br810_2' branch.
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2016  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 const int MEDCouplingUMesh::MEDCOUPLING2VTKTYPETRADUCER[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};
59 /// @endcond
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New()
62 {
63   return new MEDCouplingUMesh;
64 }
65
66 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
67 {
68   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
69   ret->setName(meshName);
70   ret->setMeshDimension(meshDim);
71   return ret;
72 }
73
74 /*!
75  * Returns a new MEDCouplingUMesh which is a full copy of \a this one. No data is shared
76  * between \a this and the new mesh.
77  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
78  *          delete this mesh using decrRef() as it is no more needed. 
79  */
80 MEDCouplingUMesh *MEDCouplingUMesh::deepCopy() const
81 {
82   return clone(true);
83 }
84
85
86 /*!
87  * Returns a new MEDCouplingUMesh which is a copy of \a this one.
88  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
89  * this mesh are shared by the new mesh.
90  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
91  *          delete this mesh using decrRef() as it is no more needed. 
92  */
93 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
94 {
95   return new MEDCouplingUMesh(*this,recDeepCpy);
96 }
97
98 /*!
99  * This method behaves mostly like MEDCouplingUMesh::deepCopy method, except that only nodal connectivity arrays are deeply copied.
100  * The coordinates are shared between \a this and the returned instance.
101  * 
102  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
103  * \sa MEDCouplingUMesh::deepCopy
104  */
105 MEDCouplingUMesh *MEDCouplingUMesh::deepCopyConnectivityOnly() const
106 {
107   checkConnectivityFullyDefined();
108   MCAuto<MEDCouplingUMesh> ret=clone(false);
109   MCAuto<DataArrayInt> c(getNodalConnectivity()->deepCopy()),ci(getNodalConnectivityIndex()->deepCopy());
110   ret->setConnectivity(c,ci);
111   return ret.retn();
112 }
113
114 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
115 {
116   if(!other)
117     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
118   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
119   if(!otherC)
120     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
121   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
122   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
123 }
124
125 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
126 {
127   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
128   return ret;
129 }
130
131 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
132 {
133   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
134   ret.push_back(_nodal_connec);
135   ret.push_back(_nodal_connec_index);
136   return ret;
137 }
138
139 void MEDCouplingUMesh::updateTime() const
140 {
141   MEDCouplingPointSet::updateTime();
142   if(_nodal_connec)
143     {
144       updateTimeWith(*_nodal_connec);
145     }
146   if(_nodal_connec_index)
147     {
148       updateTimeWith(*_nodal_connec_index);
149     }
150 }
151
152 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
153 {
154 }
155
156 /*!
157  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
158  * then \a this mesh is most probably is writable, exchangeable and available for most
159  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
160  * this method to check that all is in order with \a this mesh.
161  *  \throw If the mesh dimension is not set.
162  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
163  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
164  *  \throw If the connectivity data array has more than one component.
165  *  \throw If the connectivity data array has a named component.
166  *  \throw If the connectivity index data array has more than one component.
167  *  \throw If the connectivity index data array has a named component.
168  */
169 void MEDCouplingUMesh::checkConsistencyLight() const
170 {
171   if(_mesh_dim<-1)
172     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
173   if(_mesh_dim!=-1)
174     MEDCouplingPointSet::checkConsistencyLight();
175   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
176     {
177       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
178         {
179           std::ostringstream message;
180           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
181           throw INTERP_KERNEL::Exception(message.str().c_str());
182         }
183     }
184   if(_nodal_connec)
185     {
186       if(_nodal_connec->getNumberOfComponents()!=1)
187         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
188       if(_nodal_connec->getInfoOnComponent(0)!="")
189         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
190     }
191   else
192     if(_mesh_dim!=-1)
193       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
194   if(_nodal_connec_index)
195     {
196       if(_nodal_connec_index->getNumberOfComponents()!=1)
197         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
198       if(_nodal_connec_index->getInfoOnComponent(0)!="")
199         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
200     }
201   else
202     if(_mesh_dim!=-1)
203       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
204 }
205
206 /*!
207  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
208  * then \a this mesh is most probably is writable, exchangeable and available for all
209  * algorithms. <br> In addition to the checks performed by checkConsistencyLight(), this
210  * method thoroughly checks the nodal connectivity.
211  *  \param [in] eps - a not used parameter.
212  *  \throw If the mesh dimension is not set.
213  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
214  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
215  *  \throw If the connectivity data array has more than one component.
216  *  \throw If the connectivity data array has a named component.
217  *  \throw If the connectivity index data array has more than one component.
218  *  \throw If the connectivity index data array has a named component.
219  *  \throw If number of nodes defining an element does not correspond to the type of element.
220  *  \throw If the nodal connectivity includes an invalid node id.
221  */
222 void MEDCouplingUMesh::checkConsistency(double eps) const
223 {
224   checkConsistencyLight();
225   if(_mesh_dim==-1)
226     return ;
227   int meshDim=getMeshDimension();
228   int nbOfNodes=getNumberOfNodes();
229   int nbOfCells=getNumberOfCells();
230   const int *ptr=_nodal_connec->getConstPointer();
231   const int *ptrI=_nodal_connec_index->getConstPointer();
232   for(int i=0;i<nbOfCells;i++)
233     {
234       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
235       if((int)cm.getDimension()!=meshDim)
236         {
237           std::ostringstream oss;
238           oss << "MEDCouplingUMesh::checkConsistency : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
239           throw INTERP_KERNEL::Exception(oss.str());
240         }
241       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
242       if(!cm.isDynamic())
243         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
244           {
245             std::ostringstream oss;
246             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
247             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
248             throw INTERP_KERNEL::Exception(oss.str());
249           }
250       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
251         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
252           {
253             std::ostringstream oss;
254             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
255             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
256             throw INTERP_KERNEL::Exception(oss.str());
257           }
258       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
259         {
260           int nodeId=*w;
261           if(nodeId>=0)
262             {
263               if(nodeId>=nbOfNodes)
264                 {
265                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
266                   throw INTERP_KERNEL::Exception(oss.str());
267                 }
268             }
269           else if(nodeId<-1)
270             {
271               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
272               throw INTERP_KERNEL::Exception(oss.str());
273             }
274           else
275             {
276               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
277                 {
278                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
279                   throw INTERP_KERNEL::Exception(oss.str());
280                 }
281             }
282         }
283     }
284 }
285
286 /*!
287  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
288  * elements contained in the mesh. For more info on the mesh dimension see
289  * \ref MEDCouplingUMeshPage.
290  *  \param [in] meshDim - a new mesh dimension.
291  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
292  */
293 void MEDCouplingUMesh::setMeshDimension(int meshDim)
294 {
295   if(meshDim<-1 || meshDim>3)
296     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
297   _mesh_dim=meshDim;
298   declareAsNew();
299 }
300
301 /*!
302  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
303  * 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.
304  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
305  *
306  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
307  *
308  *  \if ENABLE_EXAMPLES
309  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
310  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
311  *  \endif
312  */
313 void MEDCouplingUMesh::allocateCells(int nbOfCells)
314 {
315   if(nbOfCells<0)
316     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
317   if(_nodal_connec_index)
318     {
319       _nodal_connec_index->decrRef();
320     }
321   if(_nodal_connec)
322     {
323       _nodal_connec->decrRef();
324     }
325   _nodal_connec_index=DataArrayInt::New();
326   _nodal_connec_index->reserve(nbOfCells+1);
327   _nodal_connec_index->pushBackSilent(0);
328   _nodal_connec=DataArrayInt::New();
329   _nodal_connec->reserve(2*nbOfCells);
330   _types.clear();
331   declareAsNew();
332 }
333
334 /*!
335  * Appends a cell to the connectivity array. For deeper understanding what is
336  * happening see \ref MEDCouplingUMeshNodalConnectivity.
337  *  \param [in] type - type of cell to add.
338  *  \param [in] size - number of nodes constituting this cell.
339  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
340  * 
341  *  \if ENABLE_EXAMPLES
342  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
343  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
344  *  \endif
345  */
346 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
347 {
348   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
349   if(_nodal_connec_index==0)
350     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
351   if((int)cm.getDimension()==_mesh_dim)
352     {
353       if(!cm.isDynamic())
354         if(size!=(int)cm.getNumberOfNodes())
355           {
356             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
357             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
358             throw INTERP_KERNEL::Exception(oss.str());
359           }
360       int idx=_nodal_connec_index->back();
361       int val=idx+size+1;
362       _nodal_connec_index->pushBackSilent(val);
363       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
364       _types.insert(type);
365     }
366   else
367     {
368       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
369       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
370       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
371       throw INTERP_KERNEL::Exception(oss.str());
372     }
373 }
374
375 /*!
376  * Compacts data arrays to release unused memory. This method is to be called after
377  * finishing cell insertion using \a this->insertNextCell().
378  * 
379  *  \if ENABLE_EXAMPLES
380  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
381  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
382  *  \endif
383  */
384 void MEDCouplingUMesh::finishInsertingCells()
385 {
386   _nodal_connec->pack();
387   _nodal_connec_index->pack();
388   _nodal_connec->declareAsNew();
389   _nodal_connec_index->declareAsNew();
390   updateTime();
391 }
392
393 /*!
394  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
395  * Useful for python users.
396  */
397 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
398 {
399   return new MEDCouplingUMeshCellIterator(this);
400 }
401
402 /*!
403  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
404  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
405  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
406  * Useful for python users.
407  */
408 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
409 {
410   if(!checkConsecutiveCellTypes())
411     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
412   return new MEDCouplingUMeshCellByTypeEntry(this);
413 }
414
415 /*!
416  * Returns a set of all cell types available in \a this mesh.
417  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
418  * \warning this method does not throw any exception even if \a this is not defined.
419  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
420  */
421 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
422 {
423   return _types;
424 }
425
426 /*!
427  * This method returns the sorted list of geometric types in \a this.
428  * 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
429  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
430  *
431  * \throw if connectivity in \a this is not correctly defined.
432  *  
433  * \sa MEDCouplingMesh::getAllGeoTypes
434  */
435 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
436 {
437   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
438   checkConnectivityFullyDefined();
439   int nbOfCells(getNumberOfCells());
440   if(nbOfCells==0)
441     return ret;
442   if(getNodalConnectivityArrayLen()<1)
443     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
444   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
445   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
446   for(int i=1;i<nbOfCells;i++,ci++)
447     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
448       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
449   return ret;
450 }
451
452 /*!
453  * This method is a method that compares \a this and \a other.
454  * This method compares \b all attributes, even names and component names.
455  */
456 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
457 {
458   if(!other)
459     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
460   std::ostringstream oss; oss.precision(15);
461   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
462   if(!otherC)
463     {
464       reason="mesh given in input is not castable in MEDCouplingUMesh !";
465       return false;
466     }
467   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
468     return false;
469   if(_mesh_dim!=otherC->_mesh_dim)
470     {
471       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
472       reason=oss.str();
473       return false;
474     }
475   if(_types!=otherC->_types)
476     {
477       oss << "umesh geometric type mismatch :\nThis geometric types are :";
478       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
479         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
480       oss << "\nOther geometric types are :";
481       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
482         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
483       reason=oss.str();
484       return false;
485     }
486   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
487     if(_nodal_connec==0 || otherC->_nodal_connec==0)
488       {
489         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
490         return false;
491       }
492   if(_nodal_connec!=otherC->_nodal_connec)
493     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
494       {
495         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
496         return false;
497       }
498   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
499     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
500       {
501         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
502         return false;
503       }
504   if(_nodal_connec_index!=otherC->_nodal_connec_index)
505     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
506       {
507         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
508         return false;
509       }
510   return true;
511 }
512
513 /*!
514  * Checks if data arrays of this mesh (node coordinates, nodal
515  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
516  * not considered.
517  *  \param [in] other - the mesh to compare with.
518  *  \param [in] prec - precision value used to compare node coordinates.
519  *  \return bool - \a true if the two meshes are same.
520  */
521 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
522 {
523   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
524   if(!otherC)
525     return false;
526   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
527     return false;
528   if(_mesh_dim!=otherC->_mesh_dim)
529     return false;
530   if(_types!=otherC->_types)
531     return false;
532   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
533     if(_nodal_connec==0 || otherC->_nodal_connec==0)
534       return false;
535   if(_nodal_connec!=otherC->_nodal_connec)
536     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
537       return false;
538   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
539     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
540       return false;
541   if(_nodal_connec_index!=otherC->_nodal_connec_index)
542     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
543       return false;
544   return true;
545 }
546
547 /*!
548  * Checks if \a this and \a other meshes are geometrically equivalent with high
549  * probability, else an exception is thrown. The meshes are considered equivalent if
550  * (1) meshes contain the same number of nodes and the same number of elements of the
551  * same types (2) three cells of the two meshes (first, last and middle) are based
552  * on coincident nodes (with a specified precision).
553  *  \param [in] other - the mesh to compare with.
554  *  \param [in] prec - the precision used to compare nodes of the two meshes.
555  *  \throw If the two meshes do not match.
556  */
557 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
558 {
559   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
560   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
561   if(!otherC)
562     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
563 }
564
565 /*!
566  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
567  * cells each node belongs to.
568  * \warning For speed reasons, this method does not check if node ids in the nodal
569  *          connectivity correspond to the size of node coordinates array.
570  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
571  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
572  *        dividing cell ids in \a revNodal into groups each referring to one
573  *        node. Its every element (except the last one) is an index pointing to the
574  *         first id of a group of cells. For example cells sharing the node #1 are 
575  *        described by following range of indices: 
576  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
577  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
578  *        Number of cells sharing the *i*-th node is
579  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
580  * \throw If the coordinates array is not set.
581  * \throw If the nodal connectivity of cells is not defined.
582  * 
583  * \if ENABLE_EXAMPLES
584  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
585  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
586  * \endif
587  */
588 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
589 {
590   checkFullyDefined();
591   int nbOfNodes=getNumberOfNodes();
592   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
593   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
594   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
595   const int *conn=_nodal_connec->getConstPointer();
596   const int *connIndex=_nodal_connec_index->getConstPointer();
597   int nbOfCells=getNumberOfCells();
598   int nbOfEltsInRevNodal=0;
599   for(int eltId=0;eltId<nbOfCells;eltId++)
600     {
601       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
602       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
603       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
604         if(*iter>=0)//for polyhedrons
605           {
606             nbOfEltsInRevNodal++;
607             revNodalIndxPtr[(*iter)+1]++;
608           }
609     }
610   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
611   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
612   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
613   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
614   for(int eltId=0;eltId<nbOfCells;eltId++)
615     {
616       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
617       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
618       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
619         if(*iter>=0)//for polyhedrons
620           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
621     }
622 }
623
624 /// @cond INTERNAL
625
626 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
627 {
628   return id;
629 }
630
631 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
632 {
633   if(!compute)
634     return id+1;
635   else
636     {
637       if(cm.getOrientationStatus(nb,conn1,conn2))
638         return id+1;
639       else
640         return -(id+1);
641     }
642 }
643
644 class MinusOneSonsGenerator
645 {
646 public:
647   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
648   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
649   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
650   static const int DELTA=1;
651 private:
652   const INTERP_KERNEL::CellModel& _cm;
653 };
654
655 class MinusOneSonsGeneratorBiQuadratic
656 {
657 public:
658   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
659   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
660   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
661   static const int DELTA=1;
662 private:
663   const INTERP_KERNEL::CellModel& _cm;
664 };
665
666 class MinusTwoSonsGenerator
667 {
668 public:
669   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
670   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
671   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
672   static const int DELTA=2;
673 private:
674   const INTERP_KERNEL::CellModel& _cm;
675 };
676
677 class MicroEdgesGenerator2D
678 {
679 public:
680   MicroEdgesGenerator2D(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
681   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfMicroEdges(); }
682   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillMicroEdgeNodalConnectivity(sonId,nodalConn,sonNodalConn,typeOfSon); }
683   static const int DELTA=1;
684 private:
685   const INTERP_KERNEL::CellModel& _cm;
686 };
687
688 class MicroEdgesGenerator3D
689 {
690 public:
691   MicroEdgesGenerator3D(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
692   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfMicroEdges(); }
693   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillMicroEdgeNodalConnectivity(sonId,nodalConn,sonNodalConn,typeOfSon); }
694   static const int DELTA=2;
695 private:
696   const INTERP_KERNEL::CellModel& _cm;
697 };
698
699 /// @endcond
700
701 /*!
702  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
703  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
704  * describing correspondence between cells of \a this and the result meshes are
705  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
706  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
707  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
708  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
709  * \warning For speed reasons, this method does not check if node ids in the nodal
710  *          connectivity correspond to the size of node coordinates array.
711  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
712  *          to write this mesh to the MED file, its cells must be sorted using
713  *          sortCellsInMEDFileFrmt().
714  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
715  *         each cell of \a this mesh.
716  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
717  *        dividing cell ids in \a desc into groups each referring to one
718  *        cell of \a this mesh. Its every element (except the last one) is an index
719  *        pointing to the first id of a group of cells. For example cells of the
720  *        result mesh bounding the cell #1 of \a this mesh are described by following
721  *        range of indices:
722  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
723  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
724  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
725  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
726  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
727  *         by each cell of the result mesh.
728  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
729  *        in the result mesh,
730  *        dividing cell ids in \a revDesc into groups each referring to one
731  *        cell of the result mesh the same way as \a descIndx divides \a desc.
732  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
733  *        delete this mesh using decrRef() as it is no more needed.
734  *  \throw If the coordinates array is not set.
735  *  \throw If the nodal connectivity of cells is node defined.
736  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
737  *         revDescIndx == NULL.
738  * 
739  *  \if ENABLE_EXAMPLES
740  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
741  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
742  *  \endif
743  * \sa buildDescendingConnectivity2()
744  */
745 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
746 {
747   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
748 }
749
750 /*!
751  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
752  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
753  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
754  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
755  * \sa MEDCouplingUMesh::buildDescendingConnectivity
756  */
757 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
758 {
759   checkFullyDefined();
760   if(getMeshDimension()!=3)
761     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
762   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
763 }
764
765 /*!
766  * This method computes the micro edges constituting each cell in \a this. Micro edge is an edge for non quadratic cells. Micro edge is an half edge for quadratic cells.
767  * This method works for both meshes with mesh dimenstion equal to 2 or 3. Dynamical cells are not supported (polygons, polyhedrons...)
768  * 
769  * \sa explode3DMeshTo1D, buildDescendingConnectiviy
770  */
771 MEDCouplingUMesh *MEDCouplingUMesh::explodeMeshIntoMicroEdges(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
772 {
773    checkFullyDefined();
774    switch(getMeshDimension())
775      {
776      case 2:
777        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
778      case 3:
779        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
780      default:
781        throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explodeMeshIntoMicroEdges : Only 2D and 3D supported !");
782      }
783 }
784
785 /*!
786  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
787  * this->getMeshDimension(), that bound cells of \a this mesh. In
788  * addition arrays describing correspondence between cells of \a this and the result
789  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
790  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
791  *  mesh. This method differs from buildDescendingConnectivity() in that apart
792  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
793  * result meshes. So a positive id means that order of nodes in corresponding cells
794  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
795  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
796  * i.e. cell ids are one-based.
797  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
798  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
799  * \warning For speed reasons, this method does not check if node ids in the nodal
800  *          connectivity correspond to the size of node coordinates array.
801  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
802  *          to write this mesh to the MED file, its cells must be sorted using
803  *          sortCellsInMEDFileFrmt().
804  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
805  *         each cell of \a this mesh.
806  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
807  *        dividing cell ids in \a desc into groups each referring to one
808  *        cell of \a this mesh. Its every element (except the last one) is an index
809  *        pointing to the first id of a group of cells. For example cells of the
810  *        result mesh bounding the cell #1 of \a this mesh are described by following
811  *        range of indices:
812  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
813  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
814  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
815  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
816  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
817  *         by each cell of the result mesh.
818  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
819  *        in the result mesh,
820  *        dividing cell ids in \a revDesc into groups each referring to one
821  *        cell of the result mesh the same way as \a descIndx divides \a desc.
822  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
823  *        shares the node coordinates array with \a this mesh. The caller is to
824  *        delete this mesh using decrRef() as it is no more needed.
825  *  \throw If the coordinates array is not set.
826  *  \throw If the nodal connectivity of cells is node defined.
827  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
828  *         revDescIndx == NULL.
829  * 
830  *  \if ENABLE_EXAMPLES
831  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
832  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
833  *  \endif
834  * \sa buildDescendingConnectivity()
835  */
836 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
837 {
838   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
839 }
840
841 /*!
842  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
843  * For speed reasons no check of this will be done. This method calls
844  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
845  * This method lists cell by cell in \b this which are its neighbors. To compute the result
846  * only connectivities are considered.
847  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
848  * The format of return is hence \ref numbering-indirect.
849  *
850  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
851  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
852  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
853  * is equal to the last values in \b neighborsIndx.
854  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
855  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
856  */
857 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
858 {
859   MCAuto<DataArrayInt> desc=DataArrayInt::New();
860   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
861   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
862   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
863   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
864   meshDM1=0;
865   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
866 }
867
868 /*!
869  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
870  * of MEDCouplingUMesh::computeNeighborsOfCells.
871  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
872  * typically the case to extract a set a neighbours,
873  * excluding a set of meshdim-1 cells in input descending connectivity.
874  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
875  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
876  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
877  * are considered.
878  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
879  *
880  * \param [in] desc descending connectivity array.
881  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
882  * \param [in] revDesc reverse descending connectivity array.
883  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
884  * \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
885  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
886  * \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.
887  */
888 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
889                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
890 {
891   if(!desc || !descIndx || !revDesc || !revDescIndx)
892     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
893   const int *descPtr=desc->getConstPointer();
894   const int *descIPtr=descIndx->getConstPointer();
895   const int *revDescPtr=revDesc->getConstPointer();
896   const int *revDescIPtr=revDescIndx->getConstPointer();
897   //
898   int nbCells=descIndx->getNumberOfTuples()-1;
899   MCAuto<DataArrayInt> out0=DataArrayInt::New();
900   MCAuto<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
901   int *out1Ptr=out1->getPointer();
902   *out1Ptr++=0;
903   out0->reserve(desc->getNumberOfTuples());
904   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
905     {
906       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
907         {
908           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
909           s.erase(i);
910           out0->insertAtTheEnd(s.begin(),s.end());
911         }
912       *out1Ptr=out0->getNumberOfTuples();
913     }
914   neighbors=out0.retn();
915   neighborsIndx=out1.retn();
916 }
917
918 /*!
919  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
920  * For speed reasons no check of this will be done. This method calls
921  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
922  * This method lists node by node in \b this which are its neighbors. To compute the result
923  * only connectivities are considered.
924  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
925  *
926  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
927  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
928  * parameter allows to select the right part in this array (\ref numbering-indirect).
929  * The number of tuples is equal to the last values in \b neighborsIndx.
930  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
931  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
932  */
933 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
934 {
935   checkFullyDefined();
936   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
937   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
938   MCAuto<MEDCouplingUMesh> mesh1D;
939   switch(mdim)
940   {
941     case 3:
942       {
943         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
944         break;
945       }
946     case 2:
947       {
948         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
949         break;
950       }
951     case 1:
952       {
953         mesh1D=const_cast<MEDCouplingUMesh *>(this);
954         mesh1D->incrRef();
955         break;
956       }
957     default:
958       {
959         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
960       }
961   }
962   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
963   mesh1D->getReverseNodalConnectivity(desc,descIndx);
964   MCAuto<DataArrayInt> ret0(DataArrayInt::New());
965   ret0->alloc(desc->getNumberOfTuples(),1);
966   int *r0Pt(ret0->getPointer());
967   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
968   for(int i=0;i<nbNodes;i++,rni++)
969     {
970       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
971         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
972     }
973   neighbors=ret0.retn();
974   neighborsIdx=descIndx.retn();
975 }
976
977 /// @cond INTERNAL
978
979 /*!
980  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
981  * For speed reasons no check of this will be done.
982  */
983 template<class SonsGenerator>
984 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
985 {
986   if(!desc || !descIndx || !revDesc || !revDescIndx)
987     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
988   checkConnectivityFullyDefined();
989   int nbOfCells=getNumberOfCells();
990   int nbOfNodes=getNumberOfNodes();
991   MCAuto<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
992   int *revNodalIndxPtr=revNodalIndx->getPointer();
993   const int *conn=_nodal_connec->getConstPointer();
994   const int *connIndex=_nodal_connec_index->getConstPointer();
995   std::string name="Mesh constituent of "; name+=getName();
996   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
997   ret->setCoords(getCoords());
998   ret->allocateCells(2*nbOfCells);
999   descIndx->alloc(nbOfCells+1,1);
1000   MCAuto<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
1001   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
1002   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
1003     {
1004       int pos=connIndex[eltId];
1005       int posP1=connIndex[eltId+1];
1006       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
1007       SonsGenerator sg(cm);
1008       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
1009       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
1010       for(unsigned i=0;i<nbOfSons;i++)
1011         {
1012           INTERP_KERNEL::NormalizedCellType cmsId;
1013           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
1014           for(unsigned k=0;k<nbOfNodesSon;k++)
1015             if(tmp[k]>=0)
1016               revNodalIndxPtr[tmp[k]+1]++;
1017           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
1018           revDesc2->pushBackSilent(eltId);
1019         }
1020       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
1021     }
1022   int nbOfCellsM1=ret->getNumberOfCells();
1023   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
1024   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
1025   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
1026   int *revNodalPtr=revNodal->getPointer();
1027   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
1028   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
1029   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
1030     {
1031       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
1032       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
1033       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
1034         if(*iter>=0)//for polyhedrons
1035           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
1036     }
1037   //
1038   DataArrayInt *commonCells=0,*commonCellsI=0;
1039   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1040   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1041   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1042   int newNbOfCellsM1=-1;
1043   MCAuto<DataArrayInt> o2nM1=DataArrayInt::ConvertIndexArrayToO2N(nbOfCellsM1,commonCells->begin(),
1044                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1045   std::vector<bool> isImpacted(nbOfCellsM1,false);
1046   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1047     for(int work2=work[0];work2!=work[1];work2++)
1048       isImpacted[commonCellsPtr[work2]]=true;
1049   const int *o2nM1Ptr=o2nM1->getConstPointer();
1050   MCAuto<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1051   const int *n2oM1Ptr=n2oM1->getConstPointer();
1052   MCAuto<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1053   ret2->copyTinyInfoFrom(this);
1054   desc->alloc(descIndx->back(),1);
1055   int *descPtr=desc->getPointer();
1056   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1057   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1058     {
1059       if(!isImpacted[i])
1060         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1061       else
1062         {
1063           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1064             {
1065               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1066               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1067             }
1068           else
1069             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1070         }
1071     }
1072   revDesc->reserve(newNbOfCellsM1);
1073   revDescIndx->alloc(newNbOfCellsM1+1,1);
1074   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1075   const int *revDesc2Ptr=revDesc2->getConstPointer();
1076   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1077     {
1078       int oldCellIdM1=n2oM1Ptr[i];
1079       if(!isImpacted[oldCellIdM1])
1080         {
1081           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1082           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1083         }
1084       else
1085         {
1086           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1087             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1088           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1089           commonCellsIPtr++;
1090         }
1091     }
1092   //
1093   return ret2.retn();
1094 }
1095
1096 struct MEDCouplingAccVisit
1097 {
1098   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1099   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1100   int _new_nb_of_nodes;
1101 };
1102
1103 /// @endcond
1104
1105 /*!
1106  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1107  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1108  * array of cell ids. Pay attention that after conversion all algorithms work slower
1109  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1110  * conversion due presence of invalid ids in the array of cells to convert, as a
1111  * result \a this mesh contains some already converted elements. In this case the 2D
1112  * mesh remains valid but 3D mesh becomes \b inconsistent!
1113  *  \warning This method can significantly modify the order of geometric types in \a this,
1114  *          hence, to write this mesh to the MED file, its cells must be sorted using
1115  *          sortCellsInMEDFileFrmt().
1116  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1117  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1118  *         cellIdsToConvertBg.
1119  *  \throw If the coordinates array is not set.
1120  *  \throw If the nodal connectivity of cells is node defined.
1121  *  \throw If dimension of \a this mesh is not either 2 or 3.
1122  *
1123  *  \if ENABLE_EXAMPLES
1124  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1125  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1126  *  \endif
1127  */
1128 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1129 {
1130   checkFullyDefined();
1131   int dim=getMeshDimension();
1132   if(dim<2 || dim>3)
1133     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1134   int nbOfCells(getNumberOfCells());
1135   if(dim==2)
1136     {
1137       const int *connIndex=_nodal_connec_index->getConstPointer();
1138       int *conn=_nodal_connec->getPointer();
1139       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1140         {
1141           if(*iter>=0 && *iter<nbOfCells)
1142             {
1143               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1144               if(!cm.isQuadratic())
1145                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1146               else
1147                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1148             }
1149           else
1150             {
1151               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1152               oss << " in range [0," << nbOfCells << ") !";
1153               throw INTERP_KERNEL::Exception(oss.str());
1154             }
1155         }
1156     }
1157   else
1158     {
1159       int *connIndex(_nodal_connec_index->getPointer());
1160       const int *connOld(_nodal_connec->getConstPointer());
1161       MCAuto<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1162       std::vector<bool> toBeDone(nbOfCells,false);
1163       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1164         {
1165           if(*iter>=0 && *iter<nbOfCells)
1166             toBeDone[*iter]=true;
1167           else
1168             {
1169               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1170               oss << " in range [0," << nbOfCells << ") !";
1171               throw INTERP_KERNEL::Exception(oss.str());
1172             }
1173         }
1174       for(int cellId=0;cellId<nbOfCells;cellId++)
1175         {
1176           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1177           int lgthOld(posP1-pos-1);
1178           if(toBeDone[cellId])
1179             {
1180               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1181               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1182               int *tmp(new int[nbOfFaces*lgthOld+1]);
1183               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1184               for(unsigned j=0;j<nbOfFaces;j++)
1185                 {
1186                   INTERP_KERNEL::NormalizedCellType type;
1187                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1188                   work+=offset;
1189                   *work++=-1;
1190                 }
1191               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1192               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1193               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1194               delete [] tmp;
1195             }
1196           else
1197             {
1198               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1199               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1200             }
1201         }
1202       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1203     }
1204   computeTypes();
1205 }
1206
1207 /*!
1208  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1209  * polyhedrons (if \a this is a 3D mesh).
1210  *  \warning As this method is purely for user-friendliness and no optimization is
1211  *          done to avoid construction of a useless vector, this method can be costly
1212  *          in memory.
1213  *  \throw If the coordinates array is not set.
1214  *  \throw If the nodal connectivity of cells is node defined.
1215  *  \throw If dimension of \a this mesh is not either 2 or 3.
1216  */
1217 void MEDCouplingUMesh::convertAllToPoly()
1218 {
1219   int nbOfCells=getNumberOfCells();
1220   std::vector<int> cellIds(nbOfCells);
1221   for(int i=0;i<nbOfCells;i++)
1222     cellIds[i]=i;
1223   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1224 }
1225
1226 /*!
1227  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1228  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1229  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1230  * base facet of the volume and the second half of nodes describes an opposite facet
1231  * having the same number of nodes as the base one. This method converts such
1232  * connectivity to a valid polyhedral format where connectivity of each facet is
1233  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1234  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1235  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1236  * a correct orientation of the first facet of a polyhedron, else orientation of a
1237  * corrected cell is reverse.<br>
1238  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1239  * it releases the user from boring description of polyhedra connectivity in the valid
1240  * format.
1241  *  \throw If \a this->getMeshDimension() != 3.
1242  *  \throw If \a this->getSpaceDimension() != 3.
1243  *  \throw If the nodal connectivity of cells is not defined.
1244  *  \throw If the coordinates array is not set.
1245  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1246  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1247  *
1248  *  \if ENABLE_EXAMPLES
1249  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1250  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1251  *  \endif
1252  */
1253 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1254 {
1255   checkFullyDefined();
1256   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1257     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1258   int nbOfCells=getNumberOfCells();
1259   MCAuto<DataArrayInt> newCi=DataArrayInt::New();
1260   newCi->alloc(nbOfCells+1,1);
1261   int *newci=newCi->getPointer();
1262   const int *ci=_nodal_connec_index->getConstPointer();
1263   const int *c=_nodal_connec->getConstPointer();
1264   newci[0]=0;
1265   for(int i=0;i<nbOfCells;i++)
1266     {
1267       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1268       if(type==INTERP_KERNEL::NORM_POLYHED)
1269         {
1270           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1271             {
1272               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1273               throw INTERP_KERNEL::Exception(oss.str());
1274             }
1275           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1276           if(n2%2!=0)
1277             {
1278               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 !";
1279               throw INTERP_KERNEL::Exception(oss.str());
1280             }
1281           int n1=(int)(n2/2);
1282           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)
1283         }
1284       else
1285         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1286     }
1287   MCAuto<DataArrayInt> newC=DataArrayInt::New();
1288   newC->alloc(newci[nbOfCells],1);
1289   int *newc=newC->getPointer();
1290   for(int i=0;i<nbOfCells;i++)
1291     {
1292       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1293       if(type==INTERP_KERNEL::NORM_POLYHED)
1294         {
1295           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1296           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1297           *newc++=-1;
1298           for(std::size_t j=0;j<n1;j++)
1299             {
1300               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1301               newc[n1+5*j]=-1;
1302               newc[n1+5*j+1]=c[ci[i]+1+j];
1303               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1304               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1305               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1306             }
1307           newc+=n1*6;
1308         }
1309       else
1310         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1311     }
1312   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1313   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1314 }
1315
1316
1317 /*!
1318  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1319  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1320  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1321  *          to write this mesh to the MED file, its cells must be sorted using
1322  *          sortCellsInMEDFileFrmt().
1323  * \warning Cells (and most notably polyhedrons) must be correctly oriented for this to work
1324  *          properly. See orientCorrectlyPolyhedrons() and arePolyhedronsNotCorrectlyOriented().
1325  * \return \c true if at least one cell has been converted, \c false else. In the
1326  *         last case the nodal connectivity remains unchanged.
1327  * \throw If the coordinates array is not set.
1328  * \throw If the nodal connectivity of cells is not defined.
1329  * \throw If \a this->getMeshDimension() < 0.
1330  */
1331 bool MEDCouplingUMesh::unPolyze()
1332 {
1333   checkFullyDefined();
1334   int mdim=getMeshDimension();
1335   if(mdim<0)
1336     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1337   if(mdim<=1)
1338     return false;
1339   int nbOfCells=getNumberOfCells();
1340   if(nbOfCells<1)
1341     return false;
1342   int initMeshLgth=getNodalConnectivityArrayLen();
1343   int *conn=_nodal_connec->getPointer();
1344   int *index=_nodal_connec_index->getPointer();
1345   int posOfCurCell=0;
1346   int newPos=0;
1347   int lgthOfCurCell;
1348   bool ret=false;
1349   for(int i=0;i<nbOfCells;i++)
1350     {
1351       lgthOfCurCell=index[i+1]-posOfCurCell;
1352       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1353       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1354       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1355       int newLgth;
1356       if(cm.isDynamic())
1357         {
1358           switch(cm.getDimension())
1359           {
1360             case 2:
1361               {
1362                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1363                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1364                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1365                 break;
1366               }
1367             case 3:
1368               {
1369                 int nbOfFaces,lgthOfPolyhConn;
1370                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1371                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1372                 break;
1373               }
1374             case 1:
1375               {
1376                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1377                 break;
1378               }
1379           }
1380           ret=ret || (newType!=type);
1381           conn[newPos]=newType;
1382           newPos+=newLgth+1;
1383           posOfCurCell=index[i+1];
1384           index[i+1]=newPos;
1385         }
1386       else
1387         {
1388           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1389           newPos+=lgthOfCurCell;
1390           posOfCurCell+=lgthOfCurCell;
1391           index[i+1]=newPos;
1392         }
1393     }
1394   if(newPos!=initMeshLgth)
1395     _nodal_connec->reAlloc(newPos);
1396   if(ret)
1397     computeTypes();
1398   return ret;
1399 }
1400
1401 /*!
1402  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1403  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1404  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1405  *
1406  * \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 
1407  *             precision.
1408  */
1409 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1410 {
1411   checkFullyDefined();
1412   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1413     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1414   MCAuto<DataArrayDouble> coords=getCoords()->deepCopy();
1415   coords->recenterForMaxPrecision(eps);
1416   //
1417   int nbOfCells=getNumberOfCells();
1418   const int *conn=_nodal_connec->getConstPointer();
1419   const int *index=_nodal_connec_index->getConstPointer();
1420   MCAuto<DataArrayInt> connINew=DataArrayInt::New();
1421   connINew->alloc(nbOfCells+1,1);
1422   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1423   MCAuto<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1424   bool changed=false;
1425   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1426     {
1427       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1428         {
1429           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1430           changed=true;
1431         }
1432       else
1433         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1434       *connINewPtr=connNew->getNumberOfTuples();
1435     }
1436   if(changed)
1437     setConnectivity(connNew,connINew,false);
1438 }
1439
1440 /*!
1441  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1442  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1443  * the format of the returned DataArrayInt instance.
1444  * 
1445  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1446  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1447  */
1448 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1449 {
1450   checkConnectivityFullyDefined();
1451   const int *maxEltPt(std::max_element(_nodal_connec->begin(),_nodal_connec->end()));
1452   int maxElt(maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1);
1453   std::vector<bool> retS(maxElt,false);
1454   computeNodeIdsAlg(retS);
1455   return DataArrayInt::BuildListOfSwitchedOn(retS);
1456 }
1457
1458 /*!
1459  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1460  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1461  */
1462 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1463 {
1464   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1465   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1466   for(int i=0;i<nbOfCells;i++)
1467     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1468       if(conn[j]>=0)
1469         {
1470           if(conn[j]<nbOfNodes)
1471             nodeIdsInUse[conn[j]]=true;
1472           else
1473             {
1474               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1475               throw INTERP_KERNEL::Exception(oss.str());
1476             }
1477         }
1478 }
1479
1480 /*!
1481  * Finds nodes not used in any cell and returns an array giving a new id to every node
1482  * by excluding the unused nodes, for which the array holds -1. The result array is
1483  * a mapping in "Old to New" mode. 
1484  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1485  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1486  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1487  *          if the node is unused or a new id else. The caller is to delete this
1488  *          array using decrRef() as it is no more needed.  
1489  *  \throw If the coordinates array is not set.
1490  *  \throw If the nodal connectivity of cells is not defined.
1491  *  \throw If the nodal connectivity includes an invalid id.
1492  *
1493  *  \if ENABLE_EXAMPLES
1494  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1495  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1496  *  \endif
1497  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1498  */
1499 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1500 {
1501   nbrOfNodesInUse=-1;
1502   int nbOfNodes(getNumberOfNodes());
1503   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1504   ret->alloc(nbOfNodes,1);
1505   int *traducer=ret->getPointer();
1506   std::fill(traducer,traducer+nbOfNodes,-1);
1507   int nbOfCells=getNumberOfCells();
1508   const int *connIndex=_nodal_connec_index->getConstPointer();
1509   const int *conn=_nodal_connec->getConstPointer();
1510   for(int i=0;i<nbOfCells;i++)
1511     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1512       if(conn[j]>=0)
1513         {
1514           if(conn[j]<nbOfNodes)
1515             traducer[conn[j]]=1;
1516           else
1517             {
1518               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1519               throw INTERP_KERNEL::Exception(oss.str());
1520             }
1521         }
1522   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1523   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1524   return ret.retn();
1525 }
1526
1527 /*!
1528  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1529  * For each cell in \b this the number of nodes constituting cell is computed.
1530  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1531  * So for pohyhedrons some nodes can be counted several times in the returned result.
1532  * 
1533  * \return a newly allocated array
1534  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1535  */
1536 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1537 {
1538   checkConnectivityFullyDefined();
1539   int nbOfCells=getNumberOfCells();
1540   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1541   ret->alloc(nbOfCells,1);
1542   int *retPtr=ret->getPointer();
1543   const int *conn=getNodalConnectivity()->getConstPointer();
1544   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1545   for(int i=0;i<nbOfCells;i++,retPtr++)
1546     {
1547       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1548         *retPtr=connI[i+1]-connI[i]-1;
1549       else
1550         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1551     }
1552   return ret.retn();
1553 }
1554
1555 /*!
1556  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1557  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1558  *
1559  * \return DataArrayInt * - new object to be deallocated by the caller.
1560  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1561  */
1562 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() 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++)
1572     {
1573       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1574       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1575         *retPtr=(int)s.size();
1576       else
1577         {
1578           s.erase(-1);
1579           *retPtr=(int)s.size();
1580         }
1581     }
1582   return ret.retn();
1583 }
1584
1585 /*!
1586  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1587  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1588  * 
1589  * \return a newly allocated array
1590  */
1591 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1592 {
1593   checkConnectivityFullyDefined();
1594   int nbOfCells=getNumberOfCells();
1595   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1596   ret->alloc(nbOfCells,1);
1597   int *retPtr=ret->getPointer();
1598   const int *conn=getNodalConnectivity()->getConstPointer();
1599   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1600   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1601     {
1602       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1603       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1604     }
1605   return ret.retn();
1606 }
1607
1608 /*!
1609  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1610  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1611  * array mean that the corresponding old node is no more used. 
1612  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1613  *           this->getNumberOfNodes() before call of this method. The caller is to
1614  *           delete this array using decrRef() as it is no more needed. 
1615  *  \throw If the coordinates array is not set.
1616  *  \throw If the nodal connectivity of cells is not defined.
1617  *  \throw If the nodal connectivity includes an invalid id.
1618  *  \sa areAllNodesFetched
1619  *
1620  *  \if ENABLE_EXAMPLES
1621  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1622  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1623  *  \endif
1624  */
1625 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1626 {
1627   return MEDCouplingPointSet::zipCoordsTraducer();
1628 }
1629
1630 /*!
1631  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1632  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1633  */
1634 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1635 {
1636   switch(compType)
1637   {
1638     case 0:
1639       return AreCellsEqualPolicy0(conn,connI,cell1,cell2);
1640     case 1:
1641       return AreCellsEqualPolicy1(conn,connI,cell1,cell2);
1642     case 2:
1643       return AreCellsEqualPolicy2(conn,connI,cell1,cell2);
1644     case 3:
1645       return AreCellsEqualPolicy2NoType(conn,connI,cell1,cell2);
1646     case 7:
1647       return AreCellsEqualPolicy7(conn,connI,cell1,cell2);
1648   }
1649   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1650 }
1651
1652 /*!
1653  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1654  */
1655 int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, int cell1, int cell2)
1656 {
1657   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1658     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1659   return 0;
1660 }
1661
1662 /*!
1663  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1664  */
1665 int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, int cell1, int cell2)
1666 {
1667   int sz=connI[cell1+1]-connI[cell1];
1668   if(sz==connI[cell2+1]-connI[cell2])
1669     {
1670       if(conn[connI[cell1]]==conn[connI[cell2]])
1671         {
1672           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1673           unsigned dim=cm.getDimension();
1674           if(dim!=3)
1675             {
1676               if(dim!=1)
1677                 {
1678                   int sz1=2*(sz-1);
1679                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1680                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1681                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1682                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1683                   return work!=tmp+sz1?1:0;
1684                 }
1685               else
1686                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1687             }
1688           else
1689             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy1 : not implemented yet for meshdim == 3 !");
1690         }
1691     }
1692   return 0;
1693 }
1694
1695 /*!
1696  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1697  */
1698 int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, int cell1, int cell2)
1699 {
1700   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1701     {
1702       if(conn[connI[cell1]]==conn[connI[cell2]])
1703         {
1704           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1705           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1706           return s1==s2?1:0;
1707         }
1708     }
1709   return 0;
1710 }
1711
1712 /*!
1713  * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account !
1714  */
1715 int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *connI, int cell1, int cell2)
1716 {
1717   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1718     {
1719       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1720       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1721       return s1==s2?1:0;
1722     }
1723   return 0;
1724 }
1725
1726 /*!
1727  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1728  */
1729 int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, int cell1, int cell2)
1730 {
1731   int sz=connI[cell1+1]-connI[cell1];
1732   if(sz==connI[cell2+1]-connI[cell2])
1733     {
1734       if(conn[connI[cell1]]==conn[connI[cell2]])
1735         {
1736           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1737           unsigned dim=cm.getDimension();
1738           if(dim!=3)
1739             {
1740               if(dim!=1)
1741                 {
1742                   int sz1=2*(sz-1);
1743                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1744                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1745                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1746                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1747                   if(work!=tmp+sz1)
1748                     return 1;
1749                   else
1750                     {
1751                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1752                       std::reverse_iterator<int *> it2((int *)tmp);
1753                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1754                         return 2;
1755                       else
1756                         return 0;
1757                     }
1758
1759                   return work!=tmp+sz1?1:0;
1760                 }
1761               else
1762                 {//case of SEG2 and SEG3
1763                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1764                     return 1;
1765                   if(!cm.isQuadratic())
1766                     {
1767                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1768                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1769                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1770                         return 2;
1771                       return 0;
1772                     }
1773                   else
1774                     {
1775                       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])
1776                         return 2;
1777                       return 0;
1778                     }
1779                 }
1780             }
1781           else
1782             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy7 : not implemented yet for meshdim == 3 !");
1783         }
1784     }
1785   return 0;
1786 }
1787
1788 /*!
1789  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1790  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1791  * and result remains unchanged.
1792  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1793  * If in 'candidates' pool -1 value is considered as an empty value.
1794  * WARNING this method returns only ONE set of result !
1795  */
1796 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1797 {
1798   if(candidates.size()<1)
1799     return false;
1800   bool ret=false;
1801   std::vector<int>::const_iterator iter=candidates.begin();
1802   int start=(*iter++);
1803   for(;iter!=candidates.end();iter++)
1804     {
1805       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1806       if(status!=0)
1807         {
1808           if(!ret)
1809             {
1810               result->pushBackSilent(start);
1811               ret=true;
1812             }
1813           if(status==1)
1814             result->pushBackSilent(*iter);
1815           else
1816             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1817         }
1818     }
1819   return ret;
1820 }
1821
1822 /*!
1823  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1824  * by \a compType.
1825  * This method keeps the coordiantes of \a this. This method is time consuming.
1826  *
1827  * \param [in] compType input specifying the technique used to compare cells each other.
1828  *   - 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.
1829  *   - 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)
1830  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1831  *   - 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
1832  * can be used for users not sensitive to orientation of cell
1833  * \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.
1834  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1835  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1836  * \return the correspondance array old to new in a newly allocated array.
1837  * 
1838  */
1839 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1840 {
1841   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1842   getReverseNodalConnectivity(revNodal,revNodalI);
1843   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1844 }
1845
1846 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1847                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1848 {
1849   MCAuto<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1850   int nbOfCells=nodalI->getNumberOfTuples()-1;
1851   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1852   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1853   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1854   std::vector<bool> isFetched(nbOfCells,false);
1855   if(startCellId==0)
1856     {
1857       for(int i=0;i<nbOfCells;i++)
1858         {
1859           if(!isFetched[i])
1860             {
1861               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1862               std::vector<int> v,v2;
1863               if(connOfNode!=connPtr+connIPtr[i+1])
1864                 {
1865                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1866                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1867                   connOfNode++;
1868                 }
1869               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1870                 if(*connOfNode>=0)
1871                   {
1872                     v=v2;
1873                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1874                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1875                     v2.resize(std::distance(v2.begin(),it));
1876                   }
1877               if(v2.size()>1)
1878                 {
1879                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1880                     {
1881                       int pos=commonCellsI->back();
1882                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1883                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1884                         isFetched[*it]=true;
1885                     }
1886                 }
1887             }
1888         }
1889     }
1890   else
1891     {
1892       for(int i=startCellId;i<nbOfCells;i++)
1893         {
1894           if(!isFetched[i])
1895             {
1896               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1897               std::vector<int> v,v2;
1898               if(connOfNode!=connPtr+connIPtr[i+1])
1899                 {
1900                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1901                   connOfNode++;
1902                 }
1903               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1904                 if(*connOfNode>=0)
1905                   {
1906                     v=v2;
1907                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1908                     v2.resize(std::distance(v2.begin(),it));
1909                   }
1910               if(v2.size()>1)
1911                 {
1912                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1913                     {
1914                       int pos=commonCellsI->back();
1915                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1916                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1917                         isFetched[*it]=true;
1918                     }
1919                 }
1920             }
1921         }
1922     }
1923   commonCellsArr=commonCells.retn();
1924   commonCellsIArr=commonCellsI.retn();
1925 }
1926
1927 /*!
1928  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1929  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1930  * than \a this->getNumberOfCells() in the returned array means that there is no
1931  * corresponding cell in \a this mesh.
1932  * It is expected that \a this and \a other meshes share the same node coordinates
1933  * array, if it is not so an exception is thrown. 
1934  *  \param [in] other - the mesh to compare with.
1935  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1936  *         valid values [0,1,2], see zipConnectivityTraducer().
1937  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1938  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1939  *         values. The caller is to delete this array using
1940  *         decrRef() as it is no more needed.
1941  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1942  *         mesh.
1943  *
1944  *  \if ENABLE_EXAMPLES
1945  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1946  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1947  *  \endif
1948  *  \sa checkDeepEquivalOnSameNodesWith()
1949  *  \sa checkGeoEquivalWith()
1950  */
1951 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1952 {
1953   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1954   int nbOfCells=getNumberOfCells();
1955   static const int possibleCompType[]={0,1,2};
1956   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1957     {
1958       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1959       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1960       oss << " !";
1961       throw INTERP_KERNEL::Exception(oss.str());
1962     }
1963   MCAuto<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1964   arr=o2n->subArray(nbOfCells);
1965   arr->setName(other->getName());
1966   int tmp;
1967   if(other->getNumberOfCells()==0)
1968     return true;
1969   return arr->getMaxValue(tmp)<nbOfCells;
1970 }
1971
1972 /*!
1973  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1974  * This method tries to determine if \b other is fully included in \b this.
1975  * The main difference is that this method is not expected to throw exception.
1976  * This method has two outputs :
1977  *
1978  * \param other other mesh
1979  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1980  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1981  */
1982 bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1983 {
1984   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1985   DataArrayInt *commonCells=0,*commonCellsI=0;
1986   int thisNbCells=getNumberOfCells();
1987   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1988   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1989   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1990   int otherNbCells=other->getNumberOfCells();
1991   MCAuto<DataArrayInt> arr2=DataArrayInt::New();
1992   arr2->alloc(otherNbCells,1);
1993   arr2->fillWithZero();
1994   int *arr2Ptr=arr2->getPointer();
1995   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1996   for(int i=0;i<nbOfCommon;i++)
1997     {
1998       int start=commonCellsPtr[commonCellsIPtr[i]];
1999       if(start<thisNbCells)
2000         {
2001           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
2002             {
2003               int sig=commonCellsPtr[j]>0?1:-1;
2004               int val=std::abs(commonCellsPtr[j])-1;
2005               if(val>=thisNbCells)
2006                 arr2Ptr[val-thisNbCells]=sig*(start+1);
2007             }
2008         }
2009     }
2010   arr2->setName(other->getName());
2011   if(arr2->presenceOfValue(0))
2012     return false;
2013   arr=arr2.retn();
2014   return true;
2015 }
2016
2017 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
2018 {
2019   if(!other)
2020     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
2021   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
2022   if(!otherC)
2023     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
2024   std::vector<const MEDCouplingUMesh *> ms(2);
2025   ms[0]=this;
2026   ms[1]=otherC;
2027   return MergeUMeshesOnSameCoords(ms);
2028 }
2029
2030 /*!
2031  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2032  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2033  * cellIds is not given explicitely but by a range python like.
2034  * 
2035  * \param start
2036  * \param end
2037  * \param step
2038  * \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.
2039  * \return a newly allocated
2040  * 
2041  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2042  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2043  */
2044 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, int step, bool keepCoords) const
2045 {
2046   if(getMeshDimension()!=-1)
2047     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords));
2048   else
2049     {
2050       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh ");
2051       if(newNbOfCells!=1)
2052         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2053       if(start!=0)
2054         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2055       incrRef();
2056       return const_cast<MEDCouplingUMesh *>(this);
2057     }
2058 }
2059
2060 /*!
2061  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2062  * The result mesh shares or not the node coordinates array with \a this mesh depending
2063  * on \a keepCoords parameter.
2064  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2065  *           to write this mesh to the MED file, its cells must be sorted using
2066  *           sortCellsInMEDFileFrmt().
2067  *  \param [in] begin - an array of cell ids to include to the new mesh.
2068  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2069  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2070  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2071  *         by calling zipCoords().
2072  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2073  *         to delete this mesh using decrRef() as it is no more needed. 
2074  *  \throw If the coordinates array is not set.
2075  *  \throw If the nodal connectivity of cells is not defined.
2076  *  \throw If any cell id in the array \a begin is not valid.
2077  *
2078  *  \if ENABLE_EXAMPLES
2079  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2080  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2081  *  \endif
2082  */
2083 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2084 {
2085   if(getMeshDimension()!=-1)
2086     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
2087   else
2088     {
2089       if(end-begin!=1)
2090         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2091       if(begin[0]!=0)
2092         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2093       incrRef();
2094       return const_cast<MEDCouplingUMesh *>(this);
2095     }
2096 }
2097
2098 /*!
2099  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2100  *
2101  * 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.
2102  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2103  * The number of cells of \b this will remain the same with this method.
2104  *
2105  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2106  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2107  * \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 ).
2108  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2109  */
2110 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2111 {
2112   checkConnectivityFullyDefined();
2113   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2114   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2115     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2116   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2117     {
2118       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2119       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2120       throw INTERP_KERNEL::Exception(oss.str());
2121     }
2122   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2123   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2124     {
2125       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2126       throw INTERP_KERNEL::Exception(oss.str());
2127     }
2128   int nbOfCells=getNumberOfCells();
2129   bool easyAssign=true;
2130   const int *connI=_nodal_connec_index->getConstPointer();
2131   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2132   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2133     {
2134       if(*it>=0 && *it<nbOfCells)
2135         {
2136           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2137         }
2138       else
2139         {
2140           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2141           throw INTERP_KERNEL::Exception(oss.str());
2142         }
2143     }
2144   if(easyAssign)
2145     {
2146       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2147       computeTypes();
2148     }
2149   else
2150     {
2151       DataArrayInt *arrOut=0,*arrIOut=0;
2152       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2153                                                arrOut,arrIOut);
2154       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2155       setConnectivity(arrOut,arrIOut,true);
2156     }
2157 }
2158
2159 void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2160 {
2161   checkConnectivityFullyDefined();
2162   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2163   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2164     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelfSlice : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2165   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2166     {
2167       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2168       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2169       throw INTERP_KERNEL::Exception(oss.str());
2170     }
2171   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : ");
2172   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2173     {
2174       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2175       throw INTERP_KERNEL::Exception(oss.str());
2176     }
2177   int nbOfCells=getNumberOfCells();
2178   bool easyAssign=true;
2179   const int *connI=_nodal_connec_index->getConstPointer();
2180   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2181   int it=start;
2182   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2183     {
2184       if(it>=0 && it<nbOfCells)
2185         {
2186           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2187         }
2188       else
2189         {
2190           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2191           throw INTERP_KERNEL::Exception(oss.str());
2192         }
2193     }
2194   if(easyAssign)
2195     {
2196       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2197       computeTypes();
2198     }
2199   else
2200     {
2201       DataArrayInt *arrOut=0,*arrIOut=0;
2202       MEDCouplingUMesh::SetPartOfIndexedArraysSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2203                                                 arrOut,arrIOut);
2204       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2205       setConnectivity(arrOut,arrIOut,true);
2206     }
2207 }                      
2208
2209 /*!
2210  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2211  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2212  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2213  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2214  *
2215  * \param [in] begin input start of array of node ids.
2216  * \param [in] end input end of array of node ids.
2217  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2218  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2219  */
2220 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2221 {
2222   MCAuto<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2223   checkConnectivityFullyDefined();
2224   int tmp=-1;
2225   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2226   std::vector<bool> fastFinder(sz,false);
2227   for(const int *work=begin;work!=end;work++)
2228     if(*work>=0 && *work<sz)
2229       fastFinder[*work]=true;
2230   int nbOfCells=getNumberOfCells();
2231   const int *conn=getNodalConnectivity()->getConstPointer();
2232   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2233   for(int i=0;i<nbOfCells;i++)
2234     {
2235       int ref=0,nbOfHit=0;
2236       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2237         if(*work2>=0)
2238           {
2239             ref++;
2240             if(fastFinder[*work2])
2241               nbOfHit++;
2242           }
2243       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2244         cellIdsKept->pushBackSilent(i);
2245     }
2246   cellIdsKeptArr=cellIdsKept.retn();
2247 }
2248
2249 /*!
2250  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2251  * this->getMeshDimension(), that bound some cells of \a this mesh.
2252  * The cells of lower dimension to include to the result mesh are selected basing on
2253  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2254  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2255  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2256  * created mesh shares the node coordinates array with \a this mesh. 
2257  *  \param [in] begin - the array of node ids.
2258  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2259  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2260  *         array \a begin are added, else cells whose any node is in the
2261  *         array \a begin are added.
2262  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2263  *         to delete this mesh using decrRef() as it is no more needed. 
2264  *  \throw If the coordinates array is not set.
2265  *  \throw If the nodal connectivity of cells is not defined.
2266  *  \throw If any node id in \a begin is not valid.
2267  *
2268  *  \if ENABLE_EXAMPLES
2269  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2270  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2271  *  \endif
2272  */
2273 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2274 {
2275   MCAuto<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2276   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2277   MCAuto<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2278   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2279   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2280 }
2281
2282 /*!
2283  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2284  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2285  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2286  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2287  *         by calling zipCoords().
2288  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2289  *         to delete this mesh using decrRef() as it is no more needed. 
2290  *  \throw If the coordinates array is not set.
2291  *  \throw If the nodal connectivity of cells is not defined.
2292  *
2293  *  \if ENABLE_EXAMPLES
2294  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2295  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2296  *  \endif
2297  */
2298 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2299 {
2300   DataArrayInt *desc=DataArrayInt::New();
2301   DataArrayInt *descIndx=DataArrayInt::New();
2302   DataArrayInt *revDesc=DataArrayInt::New();
2303   DataArrayInt *revDescIndx=DataArrayInt::New();
2304   //
2305   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2306   revDesc->decrRef();
2307   desc->decrRef();
2308   descIndx->decrRef();
2309   int nbOfCells=meshDM1->getNumberOfCells();
2310   const int *revDescIndxC=revDescIndx->getConstPointer();
2311   std::vector<int> boundaryCells;
2312   for(int i=0;i<nbOfCells;i++)
2313     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2314       boundaryCells.push_back(i);
2315   revDescIndx->decrRef();
2316   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2317   return ret;
2318 }
2319
2320 /*!
2321  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2322  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2323  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2324  */
2325 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2326 {
2327   checkFullyDefined();
2328   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2329   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2330   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2331   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2332   //
2333   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2334   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2335   //
2336   MCAuto<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2337   MCAuto<DataArrayInt> faceIds=tmp->findIdsEqual(1); tmp=(DataArrayInt*)0;
2338   const int *revDescPtr=revDesc->getConstPointer();
2339   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2340   int nbOfCells=getNumberOfCells();
2341   std::vector<bool> ret1(nbOfCells,false);
2342   int sz=0;
2343   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2344     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2345       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2346   //
2347   DataArrayInt *ret2=DataArrayInt::New();
2348   ret2->alloc(sz,1);
2349   int *ret2Ptr=ret2->getPointer();
2350   sz=0;
2351   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2352     if(*it)
2353       *ret2Ptr++=sz;
2354   ret2->setName("BoundaryCells");
2355   return ret2;
2356 }
2357
2358 /*!
2359  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2360  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2361  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2362  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2363  *
2364  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2365  * 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
2366  * equals a cell in \b otherDimM1OnSameCoords.
2367  *
2368  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2369  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2370  *
2371  * \param [in] otherDimM1OnSameCoords
2372  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2373  * \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
2374  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2375  */
2376 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2377 {
2378   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2379     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2380   checkConnectivityFullyDefined();
2381   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2382   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2383     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2384   MCAuto<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2385   MCAuto<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2386   MCAuto<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2387   MCAuto<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2388   MCAuto<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2389   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2390   DataArrayInt *idsOtherInConsti=0;
2391   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2392   MCAuto<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2393   if(!b)
2394     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2395   std::set<int> s1;
2396   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2397     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2398   MCAuto<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2399   s1arr_renum1->sort();
2400   cellIdsRk0=s0arr.retn();
2401   //cellIdsRk1=s_renum1.retn();
2402   cellIdsRk1=s1arr_renum1.retn();
2403 }
2404
2405 /*!
2406  * 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
2407  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2408  * 
2409  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2410  */
2411 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2412 {
2413   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2414   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2415   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2416   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2417   //
2418   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2419   revDesc=0; desc=0; descIndx=0;
2420   MCAuto<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2421   MCAuto<DataArrayInt> part=revDescIndx2->findIdsEqual(1);
2422   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2423 }
2424
2425 /*!
2426  * Finds nodes lying on the boundary of \a this mesh.
2427  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2428  *          nodes. The caller is to delete this array using decrRef() as it is no
2429  *          more needed.
2430  *  \throw If the coordinates array is not set.
2431  *  \throw If the nodal connectivity of cells is node defined.
2432  *
2433  *  \if ENABLE_EXAMPLES
2434  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2435  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2436  *  \endif
2437  */
2438 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2439 {
2440   MCAuto<MEDCouplingUMesh> skin=computeSkin();
2441   return skin->computeFetchedNodeIds();
2442 }
2443
2444 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2445 {
2446   incrRef();
2447   return const_cast<MEDCouplingUMesh *>(this);
2448 }
2449
2450 /*!
2451  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2452  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2453  * 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.
2454  * 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.
2455  * 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.
2456  *
2457  * \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
2458  *             parameter is altered during the call.
2459  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2460  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2461  * \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.
2462  *
2463  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2464  */
2465 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2466                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2467 {
2468   typedef MCAuto<DataArrayInt> DAInt;
2469   typedef MCAuto<MEDCouplingUMesh> MCUMesh;
2470
2471   checkFullyDefined();
2472   otherDimM1OnSameCoords.checkFullyDefined();
2473   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2474     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2475   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2476     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2477
2478   // Checking star-shaped M1 group:
2479   DAInt dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2480   MCUMesh meshM2 = otherDimM1OnSameCoords.buildDescendingConnectivity(dt0, dit0, rdt0, rdit0);
2481   DAInt dsi = rdit0->deltaShiftIndex();
2482   DAInt idsTmp0 = dsi->findIdsNotInRange(-1, 3);
2483   if(idsTmp0->getNumberOfTuples())
2484     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group: group is too complex: some points (or edges) have more than two connected segments (or faces)!");
2485   dt0=0; dit0=0; rdt0=0; rdit0=0; idsTmp0=0;
2486
2487   // Get extreme nodes from the group (they won't be duplicated), ie nodes belonging to boundary cells of M1
2488   DAInt xtremIdsM2 = dsi->findIdsEqual(1); dsi = 0;
2489   MCUMesh meshM2Part = static_cast<MEDCouplingUMesh *>(meshM2->buildPartOfMySelf(xtremIdsM2->begin(), xtremIdsM2->end(),true));
2490   DAInt xtrem = meshM2Part->computeFetchedNodeIds();
2491   // Remove from the list points on the boundary of the M0 mesh (those need duplication!)
2492   dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2493   MCUMesh m0desc = buildDescendingConnectivity(dt0, dit0, rdt0, rdit0); dt0=0; dit0=0; rdt0=0;
2494   dsi = rdit0->deltaShiftIndex();
2495   DAInt boundSegs = dsi->findIdsEqual(1);   // boundary segs/faces of the M0 mesh
2496   MCUMesh m0descSkin = static_cast<MEDCouplingUMesh *>(m0desc->buildPartOfMySelf(boundSegs->begin(),boundSegs->end(), true));
2497   DAInt fNodes = m0descSkin->computeFetchedNodeIds();
2498   // In 3D, some points on the boundary of M0 still need duplication:
2499   DAInt notDup = 0;
2500   if (getMeshDimension() == 3)
2501     {
2502       DAInt dnu1=DataArrayInt::New(), dnu2=DataArrayInt::New(), dnu3=DataArrayInt::New(), dnu4=DataArrayInt::New();
2503       MCUMesh m0descSkinDesc = m0descSkin->buildDescendingConnectivity(dnu1, dnu2, dnu3, dnu4);
2504       dnu1=0;dnu2=0;dnu3=0;dnu4=0;
2505       DataArrayInt * corresp=0;
2506       meshM2->areCellsIncludedIn(m0descSkinDesc,2,corresp);
2507       DAInt validIds = corresp->findIdsInRange(0, meshM2->getNumberOfCells());
2508       corresp->decrRef();
2509       if (validIds->getNumberOfTuples())
2510         {
2511           MCUMesh m1IntersecSkin = static_cast<MEDCouplingUMesh *>(m0descSkinDesc->buildPartOfMySelf(validIds->begin(), validIds->end(), true));
2512           DAInt notDuplSkin = m1IntersecSkin->findBoundaryNodes();
2513           DAInt fNodes1 = fNodes->buildSubstraction(notDuplSkin);
2514           notDup = xtrem->buildSubstraction(fNodes1);
2515         }
2516       else
2517         notDup = xtrem->buildSubstraction(fNodes);
2518     }
2519   else
2520     notDup = xtrem->buildSubstraction(fNodes);
2521
2522   // Now compute cells around group (i.e. cells where we will do the propagation to identify the two sub-sets delimited by the group)
2523   DAInt m1Nodes = otherDimM1OnSameCoords.computeFetchedNodeIds();
2524   DAInt dupl = m1Nodes->buildSubstraction(notDup);
2525   DAInt cellsAroundGroup = getCellIdsLyingOnNodes(dupl->begin(), dupl->end(), false);  // false= take cell in, even if not all nodes are in notDup
2526
2527   //
2528   MCUMesh m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellsAroundGroup->begin(),cellsAroundGroup->end(),true));
2529   int nCells2 = m0Part2->getNumberOfCells();
2530   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2531   MCUMesh m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2532
2533   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2534   DataArrayInt *tmp00=0,*tmp11=0;
2535   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2536   DAInt neighInit00(tmp00);
2537   DAInt neighIInit00(tmp11);
2538   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2539   DataArrayInt *idsTmp=0;
2540   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2541   DAInt ids(idsTmp);
2542   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2543   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2544   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2545   DataArrayInt *tmp0=0,*tmp1=0;
2546   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2547   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2548   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2549   DAInt neigh00(tmp0);
2550   DAInt neighI00(tmp1);
2551
2552   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2553   int seed = 0, nIter = 0;
2554   int nIterMax = nCells2+1; // Safety net for the loop
2555   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2556   hitCells->fillWithValue(-1);
2557   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2558   cellsToModifyConn0_torenum->alloc(0,1);
2559   while (nIter < nIterMax)
2560     {
2561       DAInt t = hitCells->findIdsEqual(-1);
2562       if (!t->getNumberOfTuples())
2563         break;
2564       // Connex zone without the crack (to compute the next seed really)
2565       int dnu;
2566       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2567       int cnt = 0;
2568       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2569         hitCells->setIJ(*ptr,0,1);
2570       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2571       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2572       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2573       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2574       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2575       DAInt nonHitCells = hitCells->findIdsEqual(-1);
2576       DAInt intersec = nonHitCells->buildIntersection(comple);
2577       if (intersec->getNumberOfTuples())
2578         { seed = intersec->getIJ(0,0); }
2579       else
2580         { break; }
2581       nIter++;
2582     }
2583   if (nIter >= nIterMax)
2584     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2585
2586   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2587   cellsToModifyConn0_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2588   cellsToModifyConn1_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2589   //
2590   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2591   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2592   nodeIdsToDuplicate=dupl.retn();
2593 }
2594
2595 /*!
2596  * This method operates a modification of the connectivity and coords in \b this.
2597  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2598  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2599  * 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
2600  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2601  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2602  * 
2603  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2604  * 
2605  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2606  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2607  */
2608 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2609 {
2610   int nbOfNodes=getNumberOfNodes();
2611   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2612   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2613 }
2614
2615 /*!
2616  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2617  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2618  *
2619  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2620  *
2621  * \sa renumberNodesInConn
2622  */
2623 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2624 {
2625   checkConnectivityFullyDefined();
2626   int *conn(getNodalConnectivity()->getPointer());
2627   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2628   int nbOfCells(getNumberOfCells());
2629   for(int i=0;i<nbOfCells;i++)
2630     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2631       {
2632         int& node=conn[iconn];
2633         if(node>=0)//avoid polyhedron separator
2634           {
2635             node+=offset;
2636           }
2637       }
2638   _nodal_connec->declareAsNew();
2639   updateTime();
2640 }
2641
2642 /*!
2643  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2644  *  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
2645  *  of a big mesh.
2646  */
2647 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
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             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2660             if(it!=newNodeNumbersO2N.end())
2661               {
2662                 node=(*it).second;
2663               }
2664             else
2665               {
2666                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2667                 throw INTERP_KERNEL::Exception(oss.str());
2668               }
2669           }
2670       }
2671   _nodal_connec->declareAsNew();
2672   updateTime();
2673 }
2674
2675 /*!
2676  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2677  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2678  * This method is a generalization of shiftNodeNumbersInConn().
2679  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2680  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2681  *         this->getNumberOfNodes(), in "Old to New" mode. 
2682  *         See \ref numbering for more info on renumbering modes.
2683  *  \throw If the nodal connectivity of cells is not defined.
2684  *
2685  *  \if ENABLE_EXAMPLES
2686  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2687  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2688  *  \endif
2689  */
2690 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2691 {
2692   checkConnectivityFullyDefined();
2693   int *conn=getNodalConnectivity()->getPointer();
2694   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2695   int nbOfCells(getNumberOfCells());
2696   for(int i=0;i<nbOfCells;i++)
2697     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2698       {
2699         int& node=conn[iconn];
2700         if(node>=0)//avoid polyhedron separator
2701           {
2702             node=newNodeNumbersO2N[node];
2703           }
2704       }
2705   _nodal_connec->declareAsNew();
2706   updateTime();
2707 }
2708
2709 /*!
2710  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2711  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2712  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2713  * 
2714  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2715  */
2716 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2717 {
2718   checkConnectivityFullyDefined();
2719   int *conn=getNodalConnectivity()->getPointer();
2720   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2721   int nbOfCells=getNumberOfCells();
2722   for(int i=0;i<nbOfCells;i++)
2723     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2724       {
2725         int& node=conn[iconn];
2726         if(node>=0)//avoid polyhedron separator
2727           {
2728             node+=delta;
2729           }
2730       }
2731   _nodal_connec->declareAsNew();
2732   updateTime();
2733 }
2734
2735 /*!
2736  * This method operates a modification of the connectivity in \b this.
2737  * 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.
2738  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2739  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2740  * 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
2741  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2742  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2743  * 
2744  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2745  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2746  * 
2747  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2748  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2749  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2750  */
2751 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2752 {
2753   checkConnectivityFullyDefined();
2754   std::map<int,int> m;
2755   int val=offset;
2756   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2757     m[*work]=val;
2758   int *conn=getNodalConnectivity()->getPointer();
2759   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2760   int nbOfCells=getNumberOfCells();
2761   for(int i=0;i<nbOfCells;i++)
2762     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2763       {
2764         int& node=conn[iconn];
2765         if(node>=0)//avoid polyhedron separator
2766           {
2767             std::map<int,int>::iterator it=m.find(node);
2768             if(it!=m.end())
2769               node=(*it).second;
2770           }
2771       }
2772   updateTime();
2773 }
2774
2775 /*!
2776  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2777  *
2778  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2779  * After the call of this method the number of cells remains the same as before.
2780  *
2781  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2782  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2783  * be strictly in [0;this->getNumberOfCells()).
2784  *
2785  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2786  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2787  * should be contained in[0;this->getNumberOfCells()).
2788  * 
2789  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2790  * \param check
2791  */
2792 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2793 {
2794   checkConnectivityFullyDefined();
2795   int nbCells=getNumberOfCells();
2796   const int *array=old2NewBg;
2797   if(check)
2798     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2799   //
2800   const int *conn=_nodal_connec->getConstPointer();
2801   const int *connI=_nodal_connec_index->getConstPointer();
2802   MCAuto<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2803   MCAuto<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2804   const int *n2oPtr=n2o->begin();
2805   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
2806   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2807   newConn->copyStringInfoFrom(*_nodal_connec);
2808   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
2809   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2810   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2811   //
2812   int *newC=newConn->getPointer();
2813   int *newCI=newConnI->getPointer();
2814   int loc=0;
2815   newCI[0]=loc;
2816   for(int i=0;i<nbCells;i++)
2817     {
2818       int pos=n2oPtr[i];
2819       int nbOfElts=connI[pos+1]-connI[pos];
2820       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2821       loc+=nbOfElts;
2822       newCI[i+1]=loc;
2823     }
2824   //
2825   setConnectivity(newConn,newConnI);
2826   if(check)
2827     free(const_cast<int *>(array));
2828 }
2829
2830 /*!
2831  * Finds cells whose bounding boxes intersect a given bounding box.
2832  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2833  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2834  *         zMax (if in 3D). 
2835  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2836  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2837  *         extent of the bounding box of cell to produce an addition to this bounding box.
2838  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2839  *         cells. The caller is to delete this array using decrRef() as it is no more
2840  *         needed. 
2841  *  \throw If the coordinates array is not set.
2842  *  \throw If the nodal connectivity of cells is not defined.
2843  *
2844  *  \if ENABLE_EXAMPLES
2845  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2846  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2847  *  \endif
2848  */
2849 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2850 {
2851   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2852   if(getMeshDimension()==-1)
2853     {
2854       elems->pushBackSilent(0);
2855       return elems.retn();
2856     }
2857   int dim=getSpaceDimension();
2858   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2859   const int* conn      = getNodalConnectivity()->getConstPointer();
2860   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2861   const double* coords = getCoords()->getConstPointer();
2862   int nbOfCells=getNumberOfCells();
2863   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2864     {
2865       for (int i=0; i<dim; i++)
2866         {
2867           elem_bb[i*2]=std::numeric_limits<double>::max();
2868           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2869         }
2870
2871       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2872         {
2873           int node= conn[inode];
2874           if(node>=0)//avoid polyhedron separator
2875             {
2876               for (int idim=0; idim<dim; idim++)
2877                 {
2878                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2879                     {
2880                       elem_bb[idim*2] = coords[node*dim+idim] ;
2881                     }
2882                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2883                     {
2884                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2885                     }
2886                 }
2887             }
2888         }
2889       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2890         elems->pushBackSilent(ielem);
2891     }
2892   return elems.retn();
2893 }
2894
2895 /*!
2896  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2897  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2898  * added in 'elems' parameter.
2899  */
2900 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2901 {
2902   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2903   if(getMeshDimension()==-1)
2904     {
2905       elems->pushBackSilent(0);
2906       return elems.retn();
2907     }
2908   int dim=getSpaceDimension();
2909   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2910   const int* conn      = getNodalConnectivity()->getConstPointer();
2911   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2912   const double* coords = getCoords()->getConstPointer();
2913   int nbOfCells=getNumberOfCells();
2914   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2915     {
2916       for (int i=0; i<dim; i++)
2917         {
2918           elem_bb[i*2]=std::numeric_limits<double>::max();
2919           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2920         }
2921
2922       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2923         {
2924           int node= conn[inode];
2925           if(node>=0)//avoid polyhedron separator
2926             {
2927               for (int idim=0; idim<dim; idim++)
2928                 {
2929                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2930                     {
2931                       elem_bb[idim*2] = coords[node*dim+idim] ;
2932                     }
2933                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2934                     {
2935                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2936                     }
2937                 }
2938             }
2939         }
2940       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2941         elems->pushBackSilent(ielem);
2942     }
2943   return elems.retn();
2944 }
2945
2946 /*!
2947  * Returns a type of a cell by its id.
2948  *  \param [in] cellId - the id of the cell of interest.
2949  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2950  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2951  */
2952 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2953 {
2954   const int *ptI=_nodal_connec_index->getConstPointer();
2955   const int *pt=_nodal_connec->getConstPointer();
2956   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2957     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2958   else
2959     {
2960       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2961       throw INTERP_KERNEL::Exception(oss.str());
2962     }
2963 }
2964
2965 /*!
2966  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2967  * This method does not throw exception if geometric type \a type is not in \a this.
2968  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2969  * The coordinates array is not considered here.
2970  *
2971  * \param [in] type the geometric type
2972  * \return cell ids in this having geometric type \a type.
2973  */
2974 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2975 {
2976
2977   MCAuto<DataArrayInt> ret=DataArrayInt::New();
2978   ret->alloc(0,1);
2979   checkConnectivityFullyDefined();
2980   int nbCells=getNumberOfCells();
2981   int mdim=getMeshDimension();
2982   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2983   if(mdim!=(int)cm.getDimension())
2984     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2985   const int *ptI=_nodal_connec_index->getConstPointer();
2986   const int *pt=_nodal_connec->getConstPointer();
2987   for(int i=0;i<nbCells;i++)
2988     {
2989       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2990         ret->pushBackSilent(i);
2991     }
2992   return ret.retn();
2993 }
2994
2995 /*!
2996  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2997  */
2998 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2999 {
3000   const int *ptI=_nodal_connec_index->getConstPointer();
3001   const int *pt=_nodal_connec->getConstPointer();
3002   int nbOfCells=getNumberOfCells();
3003   int ret=0;
3004   for(int i=0;i<nbOfCells;i++)
3005     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
3006       ret++;
3007   return ret;
3008 }
3009
3010 /*!
3011  * Returns the nodal connectivity of a given cell.
3012  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
3013  * all returned node ids can be used in getCoordinatesOfNode().
3014  *  \param [in] cellId - an id of the cell of interest.
3015  *  \param [in,out] conn - a vector where the node ids are appended. It is not
3016  *         cleared before the appending.
3017  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
3018  */
3019 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
3020 {
3021   const int *ptI=_nodal_connec_index->getConstPointer();
3022   const int *pt=_nodal_connec->getConstPointer();
3023   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
3024     if(*w>=0)
3025       conn.push_back(*w);
3026 }
3027
3028 std::string MEDCouplingUMesh::simpleRepr() const
3029 {
3030   static const char msg0[]="No coordinates specified !";
3031   std::ostringstream ret;
3032   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
3033   ret << "Description of mesh : \"" << getDescription() << "\"\n";
3034   int tmpp1,tmpp2;
3035   double tt=getTime(tmpp1,tmpp2);
3036   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
3037   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
3038   if(_mesh_dim>=-1)
3039     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
3040   else
3041     { ret << " Mesh dimension has not been set or is invalid !"; }
3042   if(_coords!=0)
3043     {
3044       const int spaceDim=getSpaceDimension();
3045       ret << spaceDim << "\nInfo attached on space dimension : ";
3046       for(int i=0;i<spaceDim;i++)
3047         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3048       ret << "\n";
3049     }
3050   else
3051     ret << msg0 << "\n";
3052   ret << "Number of nodes : ";
3053   if(_coords!=0)
3054     ret << getNumberOfNodes() << "\n";
3055   else
3056     ret << msg0 << "\n";
3057   ret << "Number of cells : ";
3058   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3059     ret << getNumberOfCells() << "\n";
3060   else
3061     ret << "No connectivity specified !" << "\n";
3062   ret << "Cell types present : ";
3063   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3064     {
3065       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3066       ret << cm.getRepr() << " ";
3067     }
3068   ret << "\n";
3069   return ret.str();
3070 }
3071
3072 std::string MEDCouplingUMesh::advancedRepr() const
3073 {
3074   std::ostringstream ret;
3075   ret << simpleRepr();
3076   ret << "\nCoordinates array : \n___________________\n\n";
3077   if(_coords)
3078     _coords->reprWithoutNameStream(ret);
3079   else
3080     ret << "No array set !\n";
3081   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3082   reprConnectivityOfThisLL(ret);
3083   return ret.str();
3084 }
3085
3086 /*!
3087  * This method returns a C++ code that is a dump of \a this.
3088  * This method will throw if this is not fully defined.
3089  */
3090 std::string MEDCouplingUMesh::cppRepr() const
3091 {
3092   static const char coordsName[]="coords";
3093   static const char connName[]="conn";
3094   static const char connIName[]="connI";
3095   checkFullyDefined();
3096   std::ostringstream ret; ret << "// coordinates" << std::endl;
3097   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3098   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3099   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3100   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3101   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3102   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3103   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3104   return ret.str();
3105 }
3106
3107 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3108 {
3109   std::ostringstream ret;
3110   reprConnectivityOfThisLL(ret);
3111   return ret.str();
3112 }
3113
3114 /*!
3115  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3116  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3117  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3118  * some algos).
3119  * 
3120  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3121  * 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
3122  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3123  */
3124 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3125 {
3126   int mdim=getMeshDimension();
3127   if(mdim<0)
3128     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3129   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3130   MCAuto<DataArrayInt> tmp1,tmp2;
3131   bool needToCpyCT=true;
3132   if(!_nodal_connec)
3133     {
3134       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3135       needToCpyCT=false;
3136     }
3137   else
3138     {
3139       tmp1=_nodal_connec;
3140       tmp1->incrRef();
3141     }
3142   if(!_nodal_connec_index)
3143     {
3144       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3145       needToCpyCT=false;
3146     }
3147   else
3148     {
3149       tmp2=_nodal_connec_index;
3150       tmp2->incrRef();
3151     }
3152   ret->setConnectivity(tmp1,tmp2,false);
3153   if(needToCpyCT)
3154     ret->_types=_types;
3155   if(!_coords)
3156     {
3157       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3158       ret->setCoords(coords);
3159     }
3160   else
3161     ret->setCoords(_coords);
3162   return ret.retn();
3163 }
3164
3165 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3166 {
3167   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3168     {
3169       int nbOfCells=getNumberOfCells();
3170       const int *c=_nodal_connec->getConstPointer();
3171       const int *ci=_nodal_connec_index->getConstPointer();
3172       for(int i=0;i<nbOfCells;i++)
3173         {
3174           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3175           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3176           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3177           stream << "\n";
3178         }
3179     }
3180   else
3181     stream << "Connectivity not defined !\n";
3182 }
3183
3184 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3185 {
3186   const int *ptI=_nodal_connec_index->getConstPointer();
3187   const int *pt=_nodal_connec->getConstPointer();
3188   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3189     return ptI[cellId+1]-ptI[cellId]-1;
3190   else
3191     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3192 }
3193
3194 /*!
3195  * Returns types of cells of the specified part of \a this mesh.
3196  * This method avoids computing sub-mesh explicitely to get its types.
3197  *  \param [in] begin - an array of cell ids of interest.
3198  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3199  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3200  *         describing the cell types. 
3201  *  \throw If the coordinates array is not set.
3202  *  \throw If the nodal connectivity of cells is not defined.
3203  *  \sa getAllGeoTypes()
3204  */
3205 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3206 {
3207   checkFullyDefined();
3208   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3209   const int *conn=_nodal_connec->getConstPointer();
3210   const int *connIndex=_nodal_connec_index->getConstPointer();
3211   for(const int *w=begin;w!=end;w++)
3212     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3213   return ret;
3214 }
3215
3216 /*!
3217  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3218  * Optionally updates
3219  * a set of types of cells constituting \a this mesh. 
3220  * This method is for advanced users having prepared their connectivity before. For
3221  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3222  *  \param [in] conn - the nodal connectivity array. 
3223  *  \param [in] connIndex - the nodal connectivity index array.
3224  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3225  *         mesh is updated.
3226  */
3227 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3228 {
3229   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3230   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3231   if(isComputingTypes)
3232     computeTypes();
3233   declareAsNew();
3234 }
3235
3236 /*!
3237  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3238  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3239  */
3240 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3241     _nodal_connec(0),_nodal_connec_index(0),
3242     _types(other._types)
3243 {
3244   if(other._nodal_connec)
3245     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCopy);
3246   if(other._nodal_connec_index)
3247     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCopy);
3248 }
3249
3250 MEDCouplingUMesh::~MEDCouplingUMesh()
3251 {
3252   if(_nodal_connec)
3253     _nodal_connec->decrRef();
3254   if(_nodal_connec_index)
3255     _nodal_connec_index->decrRef();
3256 }
3257
3258 /*!
3259  * Recomputes a set of cell types of \a this mesh. For more info see
3260  * \ref MEDCouplingUMeshNodalConnectivity.
3261  */
3262 void MEDCouplingUMesh::computeTypes()
3263 {
3264   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3265 }
3266
3267 /*!
3268  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3269  */
3270 void MEDCouplingUMesh::checkFullyDefined() const
3271 {
3272   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3273     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3274 }
3275
3276 /*!
3277  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3278  */
3279 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3280 {
3281   if(!_nodal_connec_index || !_nodal_connec)
3282     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3283 }
3284
3285 /*!
3286  * Returns a number of cells constituting \a this mesh. 
3287  *  \return int - the number of cells in \a this mesh.
3288  *  \throw If the nodal connectivity of cells is not defined.
3289  */
3290 int MEDCouplingUMesh::getNumberOfCells() const
3291
3292   if(_nodal_connec_index)
3293     return _nodal_connec_index->getNumberOfTuples()-1;
3294   else
3295     if(_mesh_dim==-1)
3296       return 1;
3297     else
3298       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3299 }
3300
3301 /*!
3302  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3303  * mesh. For more info see \ref meshes.
3304  *  \return int - the dimension of \a this mesh.
3305  *  \throw If the mesh dimension is not defined using setMeshDimension().
3306  */
3307 int MEDCouplingUMesh::getMeshDimension() const
3308 {
3309   if(_mesh_dim<-1)
3310     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3311   return _mesh_dim;
3312 }
3313
3314 /*!
3315  * Returns a length of the nodal connectivity array.
3316  * This method is for test reason. Normally the integer returned is not useable by
3317  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3318  *  \return int - the length of the nodal connectivity array.
3319  */
3320 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3321 {
3322   return _nodal_connec->getNbOfElems();
3323 }
3324
3325 /*!
3326  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3327  */
3328 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3329 {
3330   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3331   tinyInfo.push_back(getMeshDimension());
3332   tinyInfo.push_back(getNumberOfCells());
3333   if(_nodal_connec)
3334     tinyInfo.push_back(getNodalConnectivityArrayLen());
3335   else
3336     tinyInfo.push_back(-1);
3337 }
3338
3339 /*!
3340  * First step of unserialization process.
3341  */
3342 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3343 {
3344   return tinyInfo[6]<=0;
3345 }
3346
3347 /*!
3348  * Second step of serialization process.
3349  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3350  * \param a1
3351  * \param a2
3352  * \param littleStrings
3353  */
3354 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3355 {
3356   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3357   if(tinyInfo[5]!=-1)
3358     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3359 }
3360
3361 /*!
3362  * Third and final step of serialization process.
3363  */
3364 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3365 {
3366   MEDCouplingPointSet::serialize(a1,a2);
3367   if(getMeshDimension()>-1)
3368     {
3369       a1=DataArrayInt::New();
3370       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3371       int *ptA1=a1->getPointer();
3372       const int *conn=getNodalConnectivity()->getConstPointer();
3373       const int *index=getNodalConnectivityIndex()->getConstPointer();
3374       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3375       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3376     }
3377   else
3378     a1=0;
3379 }
3380
3381 /*!
3382  * Second and final unserialization process.
3383  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3384  */
3385 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3386 {
3387   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3388   setMeshDimension(tinyInfo[5]);
3389   if(tinyInfo[7]!=-1)
3390     {
3391       // Connectivity
3392       const int *recvBuffer=a1->getConstPointer();
3393       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3394       myConnecIndex->alloc(tinyInfo[6]+1,1);
3395       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3396       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3397       myConnec->alloc(tinyInfo[7],1);
3398       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3399       setConnectivity(myConnec, myConnecIndex);
3400     }
3401 }
3402
3403 /*!
3404  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelfSlice.
3405  * CellIds are given using range specified by a start an end and step.
3406  */
3407 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice(int start, int end, int step) const
3408 {
3409   checkFullyDefined();
3410   int ncell=getNumberOfCells();
3411   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3412   ret->_mesh_dim=_mesh_dim;
3413   ret->setCoords(_coords);
3414   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : ");
3415   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3416   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3417   int work=start;
3418   const int *conn=_nodal_connec->getConstPointer();
3419   const int *connIndex=_nodal_connec_index->getConstPointer();
3420   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3421     {
3422       if(work>=0 && work<ncell)
3423         {
3424           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3425         }
3426       else
3427         {
3428           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3429           throw INTERP_KERNEL::Exception(oss.str());
3430         }
3431     }
3432   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3433   int *newConnPtr=newConn->getPointer();
3434   std::set<INTERP_KERNEL::NormalizedCellType> types;
3435   work=start;
3436   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3437     {
3438       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3439       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3440     }
3441   ret->setConnectivity(newConn,newConnI,false);
3442   ret->_types=types;
3443   ret->copyTinyInfoFrom(this);
3444   return ret.retn();
3445 }
3446
3447 /*!
3448  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3449  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3450  * The return newly allocated mesh will share the same coordinates as \a this.
3451  */
3452 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3453 {
3454   checkConnectivityFullyDefined();
3455   int ncell=getNumberOfCells();
3456   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3457   ret->_mesh_dim=_mesh_dim;
3458   ret->setCoords(_coords);
3459   std::size_t nbOfElemsRet=std::distance(begin,end);
3460   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3461   connIndexRet[0]=0;
3462   const int *conn=_nodal_connec->getConstPointer();
3463   const int *connIndex=_nodal_connec_index->getConstPointer();
3464   int newNbring=0;
3465   for(const int *work=begin;work!=end;work++,newNbring++)
3466     {
3467       if(*work>=0 && *work<ncell)
3468         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3469       else
3470         {
3471           free(connIndexRet);
3472           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3473           throw INTERP_KERNEL::Exception(oss.str());
3474         }
3475     }
3476   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3477   int *connRetWork=connRet;
3478   std::set<INTERP_KERNEL::NormalizedCellType> types;
3479   for(const int *work=begin;work!=end;work++)
3480     {
3481       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3482       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3483     }
3484   MCAuto<DataArrayInt> connRetArr=DataArrayInt::New();
3485   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3486   MCAuto<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3487   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3488   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3489   ret->_types=types;
3490   ret->copyTinyInfoFrom(this);
3491   return ret.retn();
3492 }
3493
3494 /*!
3495  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3496  * mesh.<br>
3497  * For 1D cells, the returned field contains lengths.<br>
3498  * For 2D cells, the returned field contains areas.<br>
3499  * For 3D cells, the returned field contains volumes.
3500  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3501  *         orientation, i.e. the volume is always positive.
3502  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3503  *         and one time . The caller is to delete this field using decrRef() as it is no
3504  *         more needed.
3505  */
3506 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3507 {
3508   std::string name="MeasureOfMesh_";
3509   name+=getName();
3510   int nbelem=getNumberOfCells();
3511   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3512   field->setName(name);
3513   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3514   array->alloc(nbelem,1);
3515   double *area_vol=array->getPointer();
3516   field->setArray(array) ; array=0;
3517   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3518   field->synchronizeTimeWithMesh();
3519   if(getMeshDimension()!=-1)
3520     {
3521       int ipt;
3522       INTERP_KERNEL::NormalizedCellType type;
3523       int dim_space=getSpaceDimension();
3524       const double *coords=getCoords()->getConstPointer();
3525       const int *connec=getNodalConnectivity()->getConstPointer();
3526       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3527       for(int iel=0;iel<nbelem;iel++)
3528         {
3529           ipt=connec_index[iel];
3530           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3531           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);
3532         }
3533       if(isAbs)
3534         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3535     }
3536   else
3537     {
3538       area_vol[0]=std::numeric_limits<double>::max();
3539     }
3540   return field.retn();
3541 }
3542
3543 /*!
3544  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3545  * mesh.<br>
3546  * For 1D cells, the returned array contains lengths.<br>
3547  * For 2D cells, the returned array contains areas.<br>
3548  * For 3D cells, the returned array contains volumes.
3549  * This method avoids building explicitly a part of \a this mesh to perform the work.
3550  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3551  *         orientation, i.e. the volume is always positive.
3552  *  \param [in] begin - an array of cell ids of interest.
3553  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3554  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3555  *          delete this array using decrRef() as it is no more needed.
3556  * 
3557  *  \if ENABLE_EXAMPLES
3558  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3559  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3560  *  \endif
3561  *  \sa getMeasureField()
3562  */
3563 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3564 {
3565   std::string name="PartMeasureOfMesh_";
3566   name+=getName();
3567   int nbelem=(int)std::distance(begin,end);
3568   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3569   array->setName(name);
3570   array->alloc(nbelem,1);
3571   double *area_vol=array->getPointer();
3572   if(getMeshDimension()!=-1)
3573     {
3574       int ipt;
3575       INTERP_KERNEL::NormalizedCellType type;
3576       int dim_space=getSpaceDimension();
3577       const double *coords=getCoords()->getConstPointer();
3578       const int *connec=getNodalConnectivity()->getConstPointer();
3579       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3580       for(const int *iel=begin;iel!=end;iel++)
3581         {
3582           ipt=connec_index[*iel];
3583           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3584           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3585         }
3586       if(isAbs)
3587         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3588     }
3589   else
3590     {
3591       area_vol[0]=std::numeric_limits<double>::max();
3592     }
3593   return array.retn();
3594 }
3595
3596 /*!
3597  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3598  * \a this one. The returned field contains the dual cell volume for each corresponding
3599  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3600  *  the dual mesh in P1 sens of \a this.<br>
3601  * For 1D cells, the returned field contains lengths.<br>
3602  * For 2D cells, the returned field contains areas.<br>
3603  * For 3D cells, the returned field contains volumes.
3604  * This method is useful to check "P1*" conservative interpolators.
3605  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3606  *         orientation, i.e. the volume is always positive.
3607  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3608  *          nodes and one time. The caller is to delete this array using decrRef() as
3609  *          it is no more needed.
3610  */
3611 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3612 {
3613   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3614   std::string name="MeasureOnNodeOfMesh_";
3615   name+=getName();
3616   int nbNodes=getNumberOfNodes();
3617   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3618   double cst=1./((double)getMeshDimension()+1.);
3619   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3620   array->alloc(nbNodes,1);
3621   double *valsToFill=array->getPointer();
3622   std::fill(valsToFill,valsToFill+nbNodes,0.);
3623   const double *values=tmp->getArray()->getConstPointer();
3624   MCAuto<DataArrayInt> da=DataArrayInt::New();
3625   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3626   getReverseNodalConnectivity(da,daInd);
3627   const int *daPtr=da->getConstPointer();
3628   const int *daIPtr=daInd->getConstPointer();
3629   for(int i=0;i<nbNodes;i++)
3630     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3631       valsToFill[i]+=cst*values[*cell];
3632   ret->setMesh(this);
3633   ret->setArray(array);
3634   return ret.retn();
3635 }
3636
3637 /*!
3638  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3639  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3640  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3641  * and are normalized.
3642  * <br> \a this can be either 
3643  * - a  2D mesh in 2D or 3D space or 
3644  * - an 1D mesh in 2D space.
3645  * 
3646  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3647  *          cells and one time. The caller is to delete this field using decrRef() as
3648  *          it is no more needed.
3649  *  \throw If the nodal connectivity of cells is not defined.
3650  *  \throw If the coordinates array is not set.
3651  *  \throw If the mesh dimension is not set.
3652  *  \throw If the mesh and space dimension is not as specified above.
3653  */
3654 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3655 {
3656   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3657     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3658   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3659   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3660   int nbOfCells=getNumberOfCells();
3661   int nbComp=getMeshDimension()+1;
3662   array->alloc(nbOfCells,nbComp);
3663   double *vals=array->getPointer();
3664   const int *connI=_nodal_connec_index->getConstPointer();
3665   const int *conn=_nodal_connec->getConstPointer();
3666   const double *coords=_coords->getConstPointer();
3667   if(getMeshDimension()==2)
3668     {
3669       if(getSpaceDimension()==3)
3670         {
3671           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3672           const double *locPtr=loc->getConstPointer();
3673           for(int i=0;i<nbOfCells;i++,vals+=3)
3674             {
3675               int offset=connI[i];
3676               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3677               double n=INTERP_KERNEL::norm<3>(vals);
3678               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3679             }
3680         }
3681       else
3682         {
3683           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3684           const double *isAbsPtr=isAbs->getArray()->begin();
3685           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3686             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3687         }
3688     }
3689   else//meshdimension==1
3690     {
3691       double tmp[2];
3692       for(int i=0;i<nbOfCells;i++)
3693         {
3694           int offset=connI[i];
3695           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3696           double n=INTERP_KERNEL::norm<2>(tmp);
3697           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3698           *vals++=-tmp[1];
3699           *vals++=tmp[0];
3700         }
3701     }
3702   ret->setArray(array);
3703   ret->setMesh(this);
3704   ret->synchronizeTimeWithSupport();
3705   return ret.retn();
3706 }
3707
3708 /*!
3709  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3710  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3711  * and are normalized.
3712  * <br> \a this can be either 
3713  * - a  2D mesh in 2D or 3D space or 
3714  * - an 1D mesh in 2D space.
3715  * 
3716  * This method avoids building explicitly a part of \a this mesh to perform the work.
3717  *  \param [in] begin - an array of cell ids of interest.
3718  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3719  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3720  *          cells and one time. The caller is to delete this field using decrRef() as
3721  *          it is no more needed.
3722  *  \throw If the nodal connectivity of cells is not defined.
3723  *  \throw If the coordinates array is not set.
3724  *  \throw If the mesh dimension is not set.
3725  *  \throw If the mesh and space dimension is not as specified above.
3726  *  \sa buildOrthogonalField()
3727  *
3728  *  \if ENABLE_EXAMPLES
3729  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3730  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3731  *  \endif
3732  */
3733 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3734 {
3735   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3736     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3737   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3738   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3739   std::size_t nbelems=std::distance(begin,end);
3740   int nbComp=getMeshDimension()+1;
3741   array->alloc((int)nbelems,nbComp);
3742   double *vals=array->getPointer();
3743   const int *connI=_nodal_connec_index->getConstPointer();
3744   const int *conn=_nodal_connec->getConstPointer();
3745   const double *coords=_coords->getConstPointer();
3746   if(getMeshDimension()==2)
3747     {
3748       if(getSpaceDimension()==3)
3749         {
3750           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3751           const double *locPtr=loc->getConstPointer();
3752           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3753             {
3754               int offset=connI[*i];
3755               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3756               double n=INTERP_KERNEL::norm<3>(vals);
3757               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3758             }
3759         }
3760       else
3761         {
3762           for(std::size_t i=0;i<nbelems;i++)
3763             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3764         }
3765     }
3766   else//meshdimension==1
3767     {
3768       double tmp[2];
3769       for(const int *i=begin;i!=end;i++)
3770         {
3771           int offset=connI[*i];
3772           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3773           double n=INTERP_KERNEL::norm<2>(tmp);
3774           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3775           *vals++=-tmp[1];
3776           *vals++=tmp[0];
3777         }
3778     }
3779   ret->setArray(array);
3780   ret->setMesh(this);
3781   ret->synchronizeTimeWithSupport();
3782   return ret.retn();
3783 }
3784
3785 /*!
3786  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3787  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3788  * and are \b not normalized.
3789  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3790  *          cells and one time. The caller is to delete this field using decrRef() as
3791  *          it is no more needed.
3792  *  \throw If the nodal connectivity of cells is not defined.
3793  *  \throw If the coordinates array is not set.
3794  *  \throw If \a this->getMeshDimension() != 1.
3795  *  \throw If \a this mesh includes cells of type other than SEG2.
3796  */
3797 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3798 {
3799   if(getMeshDimension()!=1)
3800     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3801   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3802     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3803   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3804   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3805   int nbOfCells=getNumberOfCells();
3806   int spaceDim=getSpaceDimension();
3807   array->alloc(nbOfCells,spaceDim);
3808   double *pt=array->getPointer();
3809   const double *coo=getCoords()->getConstPointer();
3810   std::vector<int> conn;
3811   conn.reserve(2);
3812   for(int i=0;i<nbOfCells;i++)
3813     {
3814       conn.resize(0);
3815       getNodeIdsOfCell(i,conn);
3816       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3817     }
3818   ret->setArray(array);
3819   ret->setMesh(this);
3820   ret->synchronizeTimeWithSupport();
3821   return ret.retn();
3822 }
3823
3824 /*!
3825  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3826  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3827  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3828  * from. If a result face is shared by two 3D cells, then the face in included twice in
3829  * the result mesh.
3830  *  \param [in] origin - 3 components of a point defining location of the plane.
3831  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3832  *         must be greater than 1e-6.
3833  *  \param [in] eps - half-thickness of the plane.
3834  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3835  *         producing correspondent 2D cells. The caller is to delete this array
3836  *         using decrRef() as it is no more needed.
3837  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3838  *         not share the node coordinates array with \a this mesh. The caller is to
3839  *         delete this mesh using decrRef() as it is no more needed.  
3840  *  \throw If the coordinates array is not set.
3841  *  \throw If the nodal connectivity of cells is not defined.
3842  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3843  *  \throw If magnitude of \a vec is less than 1e-6.
3844  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3845  *  \throw If \a this includes quadratic cells.
3846  */
3847 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3848 {
3849   checkFullyDefined();
3850   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3851     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3852   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3853   if(candidates->empty())
3854     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3855   std::vector<int> nodes;
3856   DataArrayInt *cellIds1D=0;
3857   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3858   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3859   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3860   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3861   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3862   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3863   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3864   revDesc2=0; revDescIndx2=0;
3865   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3866   revDesc1=0; revDescIndx1=0;
3867   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3868   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3869   //
3870   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3871   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3872     cut3DCurve[*it]=-1;
3873   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3874   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3875   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3876                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3877                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3878   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3879   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3880   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3881   if(cellIds2->empty())
3882     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3883   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3884   ret->setCoords(mDesc1->getCoords());
3885   ret->setConnectivity(conn,connI,true);
3886   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3887   return ret.retn();
3888 }
3889
3890 /*!
3891  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3892 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
3893 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3894 the result mesh.
3895  *  \param [in] origin - 3 components of a point defining location of the plane.
3896  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3897  *         must be greater than 1e-6.
3898  *  \param [in] eps - half-thickness of the plane.
3899  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3900  *         producing correspondent segments. The caller is to delete this array
3901  *         using decrRef() as it is no more needed.
3902  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3903  *         mesh in 3D space. This mesh does not share the node coordinates array with
3904  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3905  *         no more needed. 
3906  *  \throw If the coordinates array is not set.
3907  *  \throw If the nodal connectivity of cells is not defined.
3908  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3909  *  \throw If magnitude of \a vec is less than 1e-6.
3910  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3911  *  \throw If \a this includes quadratic cells.
3912  */
3913 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3914 {
3915   checkFullyDefined();
3916   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3917     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3918   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3919   if(candidates->empty())
3920     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3921   std::vector<int> nodes;
3922   DataArrayInt *cellIds1D=0;
3923   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3924   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3925   MCAuto<DataArrayInt> desc1=DataArrayInt::New();
3926   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New();
3927   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New();
3928   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New();
3929   MCAuto<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3930   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3931   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3932   //
3933   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3934   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3935     cut3DCurve[*it]=-1;
3936   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3937   int ncellsSub=subMesh->getNumberOfCells();
3938   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3939   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3940                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3941                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3942   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3943   conn->alloc(0,1);
3944   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3945   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3946   for(int i=0;i<ncellsSub;i++)
3947     {
3948       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3949         {
3950           if(cut3DSurf[i].first!=-2)
3951             {
3952               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3953               connI->pushBackSilent(conn->getNumberOfTuples());
3954               cellIds2->pushBackSilent(i);
3955             }
3956           else
3957             {
3958               int cellId3DSurf=cut3DSurf[i].second;
3959               int offset=nodalI[cellId3DSurf]+1;
3960               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3961               for(int j=0;j<nbOfEdges;j++)
3962                 {
3963                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3964                   connI->pushBackSilent(conn->getNumberOfTuples());
3965                   cellIds2->pushBackSilent(cellId3DSurf);
3966                 }
3967             }
3968         }
3969     }
3970   if(cellIds2->empty())
3971     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3972   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3973   ret->setCoords(mDesc1->getCoords());
3974   ret->setConnectivity(conn,connI,true);
3975   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3976   return ret.retn();
3977 }
3978
3979 /*!
3980  * Finds cells whose bounding boxes intersect a given plane.
3981  *  \param [in] origin - 3 components of a point defining location of the plane.
3982  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3983  *         must be greater than 1e-6.
3984  *  \param [in] eps - half-thickness of the plane.
3985  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3986  *         cells. The caller is to delete this array using decrRef() as it is no more
3987  *         needed.
3988  *  \throw If the coordinates array is not set.
3989  *  \throw If the nodal connectivity of cells is not defined.
3990  *  \throw If \a this->getSpaceDimension() != 3.
3991  *  \throw If magnitude of \a vec is less than 1e-6.
3992  *  \sa buildSlice3D()
3993  */
3994 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3995 {
3996   checkFullyDefined();
3997   if(getSpaceDimension()!=3)
3998     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3999   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4000   if(normm<1e-6)
4001     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4002   double vec2[3];
4003   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
4004   double angle=acos(vec[2]/normm);
4005   MCAuto<DataArrayInt> cellIds;
4006   double bbox[6];
4007   if(angle>eps)
4008     {
4009       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
4010       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
4011       if(normm2/normm>1e-6)
4012         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
4013       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
4014       mw->setCoords(coo);
4015       mw->getBoundingBox(bbox);
4016       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4017       cellIds=mw->getCellsInBoundingBox(bbox,eps);
4018     }
4019   else
4020     {
4021       getBoundingBox(bbox);
4022       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4023       cellIds=getCellsInBoundingBox(bbox,eps);
4024     }
4025   return cellIds.retn();
4026 }
4027
4028 /*!
4029  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
4030  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
4031  * No consideration of coordinate is done by this method.
4032  * 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)
4033  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull.
4034  */
4035 bool MEDCouplingUMesh::isContiguous1D() const
4036 {
4037   if(getMeshDimension()!=1)
4038     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
4039   int nbCells=getNumberOfCells();
4040   if(nbCells<1)
4041     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
4042   const int *connI=_nodal_connec_index->getConstPointer();
4043   const int *conn=_nodal_connec->getConstPointer();
4044   int ref=conn[connI[0]+2];
4045   for(int i=1;i<nbCells;i++)
4046     {
4047       if(conn[connI[i]+1]!=ref)
4048         return false;
4049       ref=conn[connI[i]+2];
4050     }
4051   return true;
4052 }
4053
4054 /*!
4055  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4056  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4057  * \param pt reference point of the line
4058  * \param v normalized director vector of the line
4059  * \param eps max precision before throwing an exception
4060  * \param res output of size this->getNumberOfCells
4061  */
4062 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4063 {
4064   if(getMeshDimension()!=1)
4065     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4066   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4067     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4068   if(getSpaceDimension()!=3)
4069     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4070   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4071   const double *fPtr=f->getArray()->getConstPointer();
4072   double tmp[3];
4073   for(int i=0;i<getNumberOfCells();i++)
4074     {
4075       const double *tmp1=fPtr+3*i;
4076       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4077       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4078       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4079       double n1=INTERP_KERNEL::norm<3>(tmp);
4080       n1/=INTERP_KERNEL::norm<3>(tmp1);
4081       if(n1>eps)
4082         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4083     }
4084   const double *coo=getCoords()->getConstPointer();
4085   for(int i=0;i<getNumberOfNodes();i++)
4086     {
4087       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4088       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4089       res[i]=std::accumulate(tmp,tmp+3,0.);
4090     }
4091 }
4092
4093 /*!
4094  * 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. 
4095  * \a this is expected to be a mesh so that its space dimension is equal to its
4096  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4097  * 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).
4098  *
4099  * 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
4100  * 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).
4101  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4102  *
4103  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4104  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4105  *
4106  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4107  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4108  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4109  * \return the positive value of the distance.
4110  * \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
4111  * dimension - 1.
4112  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4113  */
4114 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4115 {
4116   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4117   if(meshDim!=spaceDim-1)
4118     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4119   if(meshDim!=2 && meshDim!=1)
4120     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4121   checkFullyDefined();
4122   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4123     { 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()); }
4124   DataArrayInt *ret1=0;
4125   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4126   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4127   MCAuto<DataArrayInt> ret1Safe(ret1);
4128   cellId=*ret1Safe->begin();
4129   return *ret0->begin();
4130 }
4131
4132 /*!
4133  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4134  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4135  * 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
4136  * 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).
4137  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4138  * 
4139  * \a this is expected to be a mesh so that its space dimension is equal to its
4140  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4141  * 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).
4142  *
4143  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4144  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4145  *
4146  * \param [in] pts the list of points in which each tuple represents a point
4147  * \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.
4148  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4149  * \throw if number of components of \a pts is not equal to the space dimension.
4150  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4151  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4152  */
4153 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4154 {
4155   if(!pts)
4156     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4157   pts->checkAllocated();
4158   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4159   if(meshDim!=spaceDim-1)
4160     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4161   if(meshDim!=2 && meshDim!=1)
4162     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4163   if(pts->getNumberOfComponents()!=spaceDim)
4164     {
4165       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4166       throw INTERP_KERNEL::Exception(oss.str());
4167     }
4168   checkFullyDefined();
4169   int nbCells=getNumberOfCells();
4170   if(nbCells==0)
4171     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4172   int nbOfPts=pts->getNumberOfTuples();
4173   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4174   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4175   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4176   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4177   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4178   const double *bbox(bboxArr->begin());
4179   switch(spaceDim)
4180   {
4181     case 3:
4182       {
4183         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4184         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4185           {
4186             double x=std::numeric_limits<double>::max();
4187             std::vector<int> elems;
4188             myTree.getMinDistanceOfMax(ptsPtr,x);
4189             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4190             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4191           }
4192         break;
4193       }
4194     case 2:
4195       {
4196         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4197         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4198           {
4199             double x=std::numeric_limits<double>::max();
4200             std::vector<int> elems;
4201             myTree.getMinDistanceOfMax(ptsPtr,x);
4202             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4203             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4204           }
4205         break;
4206       }
4207     default:
4208       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4209   }
4210   cellIds=ret1.retn();
4211   return ret0.retn();
4212 }
4213
4214 /// @cond INTERNAL
4215
4216 /*!
4217  * \param [in] pt the start pointer (included) of the coordinates of the point
4218  * \param [in] cellIdsBg the start pointer (included) of cellIds
4219  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4220  * \param [in] nc nodal connectivity
4221  * \param [in] ncI nodal connectivity index
4222  * \param [in,out] ret0 the min distance between \a this and the external input point
4223  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4224  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4225  */
4226 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)
4227 {
4228   cellId=-1;
4229   ret0=std::numeric_limits<double>::max();
4230   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4231     {
4232       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4233       {
4234         case INTERP_KERNEL::NORM_TRI3:
4235           {
4236             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4237             if(tmp<ret0)
4238               { ret0=tmp; cellId=*zeCell; }
4239             break;
4240           }
4241         case INTERP_KERNEL::NORM_QUAD4:
4242         case INTERP_KERNEL::NORM_POLYGON:
4243           {
4244             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4245             if(tmp<ret0)
4246               { ret0=tmp; cellId=*zeCell; }
4247             break;
4248           }
4249         default:
4250           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4251       }
4252     }
4253 }
4254
4255 /*!
4256  * \param [in] pt the start pointer (included) of the coordinates of the point
4257  * \param [in] cellIdsBg the start pointer (included) of cellIds
4258  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4259  * \param [in] nc nodal connectivity
4260  * \param [in] ncI nodal connectivity index
4261  * \param [in,out] ret0 the min distance between \a this and the external input point
4262  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4263  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4264  */
4265 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)
4266 {
4267   cellId=-1;
4268   ret0=std::numeric_limits<double>::max();
4269   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4270     {
4271       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4272       {
4273         case INTERP_KERNEL::NORM_SEG2:
4274           {
4275             std::size_t uselessEntry=0;
4276             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4277             tmp=sqrt(tmp);
4278             if(tmp<ret0)
4279               { ret0=tmp; cellId=*zeCell; }
4280             break;
4281           }
4282         default:
4283           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4284       }
4285     }
4286 }
4287 /// @endcond
4288
4289 /*!
4290  * Finds cells in contact with a ball (i.e. a point with precision). 
4291  * 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.
4292  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4293  *
4294  * \warning This method is suitable if the caller intends to evaluate only one
4295  *          point, for more points getCellsContainingPoints() is recommended as it is
4296  *          faster. 
4297  *  \param [in] pos - array of coordinates of the ball central point.
4298  *  \param [in] eps - ball radius.
4299  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4300  *         if there are no such cells.
4301  *  \throw If the coordinates array is not set.
4302  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4303  */
4304 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4305 {
4306   std::vector<int> elts;
4307   getCellsContainingPoint(pos,eps,elts);
4308   if(elts.empty())
4309     return -1;
4310   return elts.front();
4311 }
4312
4313 /*!
4314  * Finds cells in contact with a ball (i.e. a point with precision).
4315  * 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.
4316  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4317  * \warning This method is suitable if the caller intends to evaluate only one
4318  *          point, for more points getCellsContainingPoints() is recommended as it is
4319  *          faster. 
4320  *  \param [in] pos - array of coordinates of the ball central point.
4321  *  \param [in] eps - ball radius.
4322  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4323  *         before inserting ids.
4324  *  \throw If the coordinates array is not set.
4325  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4326  *
4327  *  \if ENABLE_EXAMPLES
4328  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4329  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4330  *  \endif
4331  */
4332 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4333 {
4334   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4335   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4336   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4337 }
4338
4339 /// @cond INTERNAL
4340
4341 namespace MEDCoupling
4342 {
4343   template<const int SPACEDIMM>
4344   class DummyClsMCUG
4345   {
4346   public:
4347     static const int MY_SPACEDIM=SPACEDIMM;
4348     static const int MY_MESHDIM=8;
4349     typedef int MyConnType;
4350     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4351     // begin
4352     // useless, but for windows compilation ...
4353     const double* getCoordinatesPtr() const { return 0; }
4354     const int* getConnectivityPtr() const { return 0; }
4355     const int* getConnectivityIndexPtr() const { return 0; }
4356     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4357     // end
4358   };
4359
4360   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MCAuto<INTERP_KERNEL::Node>,int>& m)
4361   {
4362     INTERP_KERNEL::Edge *ret(0);
4363     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]));
4364     m[n0]=bg[0]; m[n1]=bg[1];
4365     switch(typ)
4366     {
4367       case INTERP_KERNEL::NORM_SEG2:
4368         {
4369           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4370           break;
4371         }
4372       case INTERP_KERNEL::NORM_SEG3:
4373         {
4374           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4375           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4376           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4377           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4378           bool colinearity(inters.areColinears());
4379           delete e1; delete e2;
4380           if(colinearity)
4381             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4382           else
4383             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4384           break;
4385         }
4386       default:
4387         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4388     }
4389     return ret;
4390   }
4391
4392   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4393   {
4394     INTERP_KERNEL::Edge *ret=0;
4395     switch(typ)
4396     {
4397       case INTERP_KERNEL::NORM_SEG2:
4398         {
4399           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4400           break;
4401         }
4402       case INTERP_KERNEL::NORM_SEG3:
4403         {
4404           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4405           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4406           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4407           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4408           bool colinearity=inters.areColinears();
4409           delete e1; delete e2;
4410           if(colinearity)
4411             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4412           else
4413             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4414           mapp2[bg[2]].second=false;
4415           break;
4416         }
4417       default:
4418         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4419     }
4420     return ret;
4421   }
4422
4423   /*!
4424    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4425    * the global mesh 'mDesc'.
4426    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4427    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4428    */
4429   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4430                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4431   {
4432     mapp.clear();
4433     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.
4434     const double *coo=mDesc->getCoords()->getConstPointer();
4435     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4436     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4437     std::set<int> s;
4438     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4439       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4440     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4441       {
4442         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4443         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4444       }
4445     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4446     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4447       {
4448         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4449         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4450       }
4451     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4452       {
4453         if((*it2).second.second)
4454           mapp[(*it2).second.first]=(*it2).first;
4455         ((*it2).second.first)->decrRef();
4456       }
4457     return ret;
4458   }
4459
4460   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4461   {
4462     if(nodeId>=offset2)
4463       {
4464         int locId=nodeId-offset2;
4465         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4466       }
4467     if(nodeId>=offset1)
4468       {
4469         int locId=nodeId-offset1;
4470         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4471       }
4472     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4473   }
4474
4475   /**
4476    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4477    */
4478   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4479                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4480                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4481   {
4482     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4483       {
4484         int eltId1=abs(*desc1)-1;
4485         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4486           {
4487             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4488             if(it==mappRev.end())
4489               {
4490                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4491                 mapp[node]=*it1;
4492                 mappRev[*it1]=node;
4493               }
4494           }
4495       }
4496   }
4497 }
4498
4499 /// @endcond
4500
4501 template<int SPACEDIM>
4502 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4503                                                    double eps, MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4504 {
4505   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4506   int *eltsIndexPtr(eltsIndex->getPointer());
4507   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4508   const double *bbox(bboxArr->begin());
4509   int nbOfCells=getNumberOfCells();
4510   const int *conn=_nodal_connec->getConstPointer();
4511   const int *connI=_nodal_connec_index->getConstPointer();
4512   double bb[2*SPACEDIM];
4513   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4514   for(int i=0;i<nbOfPoints;i++)
4515     {
4516       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4517       for(int j=0;j<SPACEDIM;j++)
4518         {
4519           bb[2*j]=pos[SPACEDIM*i+j];
4520           bb[2*j+1]=pos[SPACEDIM*i+j];
4521         }
4522       std::vector<int> candidates;
4523       myTree.getIntersectingElems(bb,candidates);
4524       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4525         {
4526           int sz(connI[(*iter)+1]-connI[*iter]-1);
4527           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4528           bool status(false);
4529           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4530             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4531           else
4532             {
4533               if(SPACEDIM!=2)
4534                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4535               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4536               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4537               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4538               INTERP_KERNEL::QuadraticPolygon *pol(0);
4539               for(int j=0;j<sz;j++)
4540                 {
4541                   int nodeId(conn[connI[*iter]+1+j]);
4542                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4543                 }
4544               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4545                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4546               else
4547                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4548               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4549               double a(0.),b(0.),c(0.);
4550               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4551               status=pol->isInOrOut2(n);
4552               delete pol; n->decrRef();
4553             }
4554           if(status)
4555             {
4556               eltsIndexPtr[i+1]++;
4557               elts->pushBackSilent(*iter);
4558             }
4559         }
4560     }
4561 }
4562 /*!
4563  * Finds cells in contact with several balls (i.e. points with precision).
4564  * This method is an extension of getCellContainingPoint() and
4565  * getCellsContainingPoint() for the case of multiple points.
4566  * 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.
4567  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4568  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4569  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4570  *         this->getSpaceDimension() * \a nbOfPoints 
4571  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4572  *  \param [in] eps - radius of balls (i.e. the precision).
4573  *  \param [out] elts - vector returning ids of found cells.
4574  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4575  *         dividing cell ids in \a elts into groups each referring to one
4576  *         point. Its every element (except the last one) is an index pointing to the
4577  *         first id of a group of cells. For example cells in contact with the *i*-th
4578  *         point are described by following range of indices:
4579  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4580  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4581  *         Number of cells in contact with the *i*-th point is
4582  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4583  *  \throw If the coordinates array is not set.
4584  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4585  *
4586  *  \if ENABLE_EXAMPLES
4587  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4588  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4589  *  \endif
4590  */
4591 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4592                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4593 {
4594   int spaceDim=getSpaceDimension();
4595   int mDim=getMeshDimension();
4596   if(spaceDim==3)
4597     {
4598       if(mDim==3)
4599         {
4600           const double *coords=_coords->getConstPointer();
4601           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4602         }
4603       /*else if(mDim==2)
4604         {
4605
4606         }*/
4607       else
4608         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4609     }
4610   else if(spaceDim==2)
4611     {
4612       if(mDim==2)
4613         {
4614           const double *coords=_coords->getConstPointer();
4615           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4616         }
4617       else
4618         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4619     }
4620   else if(spaceDim==1)
4621     {
4622       if(mDim==1)
4623         {
4624           const double *coords=_coords->getConstPointer();
4625           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4626         }
4627       else
4628         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4629     }
4630   else
4631     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4632 }
4633
4634 /*!
4635  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4636  * least two its edges intersect each other anywhere except their extremities. An
4637  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4638  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4639  *         cleared before filling in.
4640  *  \param [in] eps - precision.
4641  *  \throw If \a this->getMeshDimension() != 2.
4642  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4643  */
4644 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4645 {
4646   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4647   if(getMeshDimension()!=2)
4648     throw INTERP_KERNEL::Exception(msg);
4649   int spaceDim=getSpaceDimension();
4650   if(spaceDim!=2 && spaceDim!=3)
4651     throw INTERP_KERNEL::Exception(msg);
4652   const int *conn=_nodal_connec->getConstPointer();
4653   const int *connI=_nodal_connec_index->getConstPointer();
4654   int nbOfCells=getNumberOfCells();
4655   std::vector<double> cell2DinS2;
4656   for(int i=0;i<nbOfCells;i++)
4657     {
4658       int offset=connI[i];
4659       int nbOfNodesForCell=connI[i+1]-offset-1;
4660       if(nbOfNodesForCell<=3)
4661         continue;
4662       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4663       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4664       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4665         cells.push_back(i);
4666       cell2DinS2.clear();
4667     }
4668 }
4669
4670 /*!
4671  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4672  *
4673  * 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.
4674  * 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.
4675  * 
4676  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4677  * This convex envelop is computed using Jarvis march algorithm.
4678  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4679  * 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)
4680  * 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.
4681  *
4682  * \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.
4683  * \sa MEDCouplingUMesh::colinearize2D
4684  */
4685 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4686 {
4687   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4688     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4689   checkFullyDefined();
4690   const double *coords=getCoords()->getConstPointer();
4691   int nbOfCells=getNumberOfCells();
4692   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4693   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4694   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4695   int *workIndexOut=nodalConnecIndexOut->getPointer();
4696   *workIndexOut=0;
4697   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4698   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4699   std::set<INTERP_KERNEL::NormalizedCellType> types;
4700   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4701   isChanged->alloc(0,1);
4702   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4703     {
4704       int pos=nodalConnecOut->getNumberOfTuples();
4705       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4706         isChanged->pushBackSilent(i);
4707       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4708       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4709     }
4710   if(isChanged->empty())
4711     return 0;
4712   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4713   _types=types;
4714   return isChanged.retn();
4715 }
4716
4717 /*!
4718  * This method is \b NOT const because it can modify \a this.
4719  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4720  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4721  * \param policy specifies the type of extrusion chosen:
4722  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4723  *   will be repeated to build each level
4724  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4725  *   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
4726  *   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
4727  *   arc.
4728  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4729  */
4730 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4731 {
4732   checkFullyDefined();
4733   mesh1D->checkFullyDefined();
4734   if(!mesh1D->isContiguous1D())
4735     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4736   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4737     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4738   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4739     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4740   if(mesh1D->getMeshDimension()!=1)
4741     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4742   bool isQuad=false;
4743   if(isPresenceOfQuadratic())
4744     {
4745       if(mesh1D->isFullyQuadratic())
4746         isQuad=true;
4747       else
4748         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4749     }
4750   int oldNbOfNodes(getNumberOfNodes());
4751   MCAuto<DataArrayDouble> newCoords;
4752   switch(policy)
4753   {
4754     case 0:
4755       {
4756         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4757         break;
4758       }
4759     case 1:
4760       {
4761         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4762         break;
4763       }
4764     default:
4765       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4766   }
4767   setCoords(newCoords);
4768   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4769   updateTime();
4770   return ret.retn();
4771 }
4772
4773 /*!
4774  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4775  * If it is not the case an exception will be thrown.
4776  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4777  * intersection of plane defined by ('origin','vec').
4778  * This method has one in/out parameter : 'cut3DCurve'.
4779  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4780  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4781  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4782  * This method will throw an exception if \a this contains a non linear segment.
4783  */
4784 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4785 {
4786   checkFullyDefined();
4787   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4788     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4789   int ncells=getNumberOfCells();
4790   int nnodes=getNumberOfNodes();
4791   double vec2[3],vec3[3],vec4[3];
4792   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4793   if(normm<1e-6)
4794     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4795   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4796   const int *conn=_nodal_connec->getConstPointer();
4797   const int *connI=_nodal_connec_index->getConstPointer();
4798   const double *coo=_coords->getConstPointer();
4799   std::vector<double> addCoo;
4800   for(int i=0;i<ncells;i++)
4801     {
4802       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4803         {
4804           if(cut3DCurve[i]==-2)
4805             {
4806               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4807               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];
4808               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4809               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4810               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4811                 {
4812                   const double *st2=coo+3*st;
4813                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4814                   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]));
4815                   if(pos>eps && pos<1-eps)
4816                     {
4817                       int nNode=((int)addCoo.size())/3;
4818                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4819                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4820                       cut3DCurve[i]=nnodes+nNode;
4821                     }
4822                 }
4823             }
4824         }
4825       else
4826         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4827     }
4828   if(!addCoo.empty())
4829     {
4830       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4831       MCAuto<DataArrayDouble> coo2=DataArrayDouble::New();
4832       coo2->alloc(newNbOfNodes,3);
4833       double *tmp=coo2->getPointer();
4834       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4835       std::copy(addCoo.begin(),addCoo.end(),tmp);
4836       DataArrayDouble::SetArrayIn(coo2,_coords);
4837     }
4838 }
4839
4840 /*!
4841  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4842  * \param mesh1D is the input 1D mesh used for translation computation.
4843  * \return newCoords new coords filled by this method. 
4844  */
4845 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4846 {
4847   int oldNbOfNodes=getNumberOfNodes();
4848   int nbOf1DCells=mesh1D->getNumberOfCells();
4849   int spaceDim=getSpaceDimension();
4850   DataArrayDouble *ret=DataArrayDouble::New();
4851   std::vector<bool> isQuads;
4852   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4853   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4854   double *retPtr=ret->getPointer();
4855   const double *coords=getCoords()->getConstPointer();
4856   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4857   std::vector<int> v;
4858   std::vector<double> c;
4859   double vec[3];
4860   v.reserve(3);
4861   c.reserve(6);
4862   for(int i=0;i<nbOf1DCells;i++)
4863     {
4864       v.resize(0);
4865       mesh1D->getNodeIdsOfCell(i,v);
4866       c.resize(0);
4867       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4868       mesh1D->getCoordinatesOfNode(v[0],c);
4869       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4870       for(int j=0;j<oldNbOfNodes;j++)
4871         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4872       if(isQuad)
4873         {
4874           c.resize(0);
4875           mesh1D->getCoordinatesOfNode(v[1],c);
4876           mesh1D->getCoordinatesOfNode(v[0],c);
4877           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4878           for(int j=0;j<oldNbOfNodes;j++)
4879             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4880         }
4881     }
4882   ret->copyStringInfoFrom(*getCoords());
4883   return ret;
4884 }
4885
4886 /*!
4887  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4888  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4889  * \return newCoords new coords filled by this method. 
4890  */
4891 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4892 {
4893   if(mesh1D->getSpaceDimension()==2)
4894     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4895   if(mesh1D->getSpaceDimension()==3)
4896     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4897   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4898 }
4899
4900 /*!
4901  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4902  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4903  * \return newCoords new coords filled by this method. 
4904  */
4905 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4906 {
4907   if(isQuad)
4908     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4909   int oldNbOfNodes=getNumberOfNodes();
4910   int nbOf1DCells=mesh1D->getNumberOfCells();
4911   if(nbOf1DCells<2)
4912     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4913   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
4914   int nbOfLevsInVec=nbOf1DCells+1;
4915   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4916   double *retPtr=ret->getPointer();
4917   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4918   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4919   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
4920   tmp->setCoords(tmp2);
4921   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4922   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4923   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4924   for(int i=1;i<nbOfLevsInVec;i++)
4925     {
4926       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4927       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4928       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4929       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4930       tmp->translate(vec);
4931       double tmp3[2],radius,alpha,alpha0;
4932       const double *p0=i+1<nbOfLevsInVec?begin:third;
4933       const double *p1=i+1<nbOfLevsInVec?end:begin;
4934       const double *p2=i+1<nbOfLevsInVec?third:end;
4935       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4936       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]);
4937       double angle=acos(cosangle/(radius*radius));
4938       tmp->rotate(end,0,angle);
4939       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4940     }
4941   return ret.retn();
4942 }
4943
4944 /*!
4945  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4946  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4947  * \return newCoords new coords filled by this method. 
4948  */
4949 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4950 {
4951   if(isQuad)
4952     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4953   int oldNbOfNodes=getNumberOfNodes();
4954   int nbOf1DCells=mesh1D->getNumberOfCells();
4955   if(nbOf1DCells<2)
4956     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4957   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
4958   int nbOfLevsInVec=nbOf1DCells+1;
4959   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4960   double *retPtr=ret->getPointer();
4961   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4962   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4963   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
4964   tmp->setCoords(tmp2);
4965   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4966   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4967   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4968   for(int i=1;i<nbOfLevsInVec;i++)
4969     {
4970       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4971       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4972       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4973       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4974       tmp->translate(vec);
4975       double tmp3[2],radius,alpha,alpha0;
4976       const double *p0=i+1<nbOfLevsInVec?begin:third;
4977       const double *p1=i+1<nbOfLevsInVec?end:begin;
4978       const double *p2=i+1<nbOfLevsInVec?third:end;
4979       double vecPlane[3]={
4980         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4981         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4982         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4983       };
4984       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4985       if(norm>1.e-7)
4986         {
4987           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4988           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4989           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4990           double s2=norm2;
4991           double c2=cos(asin(s2));
4992           double m[3][3]={
4993             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4994             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4995             {-vec2[1]*s2, vec2[0]*s2, c2}
4996           };
4997           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]};
4998           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]};
4999           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]};
5000           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
5001           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]);
5002           double angle=acos(cosangle/(radius*radius));
5003           tmp->rotate(end,vecPlane,angle);
5004         }
5005       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
5006     }
5007   return ret.retn();
5008 }
5009
5010 /*!
5011  * This method is private because not easy to use for end user. This method is const contrary to
5012  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
5013  * the coords sorted slice by slice.
5014  * \param isQuad specifies presence of quadratic cells.
5015  */
5016 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
5017 {
5018   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
5019   int nbOf2DCells(getNumberOfCells());
5020   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
5021   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
5022   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5023   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
5024   newConnI->alloc(nbOf3DCells+1,1);
5025   int *newConnIPtr(newConnI->getPointer());
5026   *newConnIPtr++=0;
5027   std::vector<int> newc;
5028   for(int j=0;j<nbOf2DCells;j++)
5029     {
5030       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
5031       *newConnIPtr++=(int)newc.size();
5032     }
5033   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
5034   int *newConnPtr(newConn->getPointer());
5035   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
5036   newConnIPtr=newConnI->getPointer();
5037   for(int iz=0;iz<nbOf1DCells;iz++)
5038     {
5039       if(iz!=0)
5040         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
5041       const int *posOfTypeOfCell(newConnIPtr);
5042       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
5043         {
5044           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
5045           if(icell!=*posOfTypeOfCell)
5046             {
5047               if(*iter!=-1)
5048                 *newConnPtr=(*iter)+iz*deltaPerLev;
5049               else
5050                 *newConnPtr=-1;
5051             }
5052           else
5053             {
5054               *newConnPtr=*iter;
5055               posOfTypeOfCell++;
5056             }
5057         }
5058     }
5059   ret->setConnectivity(newConn,newConnI,true);
5060   ret->setCoords(getCoords());
5061   return ret;
5062 }
5063
5064 /*!
5065  * Checks if \a this mesh is constituted by only quadratic cells.
5066  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
5067  *  \throw If the coordinates array is not set.
5068  *  \throw If the nodal connectivity of cells is not defined.
5069  */
5070 bool MEDCouplingUMesh::isFullyQuadratic() const
5071 {
5072   checkFullyDefined();
5073   bool ret=true;
5074   int nbOfCells=getNumberOfCells();
5075   for(int i=0;i<nbOfCells && ret;i++)
5076     {
5077       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5078       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5079       ret=cm.isQuadratic();
5080     }
5081   return ret;
5082 }
5083
5084 /*!
5085  * Checks if \a this mesh includes any quadratic cell.
5086  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5087  *  \throw If the coordinates array is not set.
5088  *  \throw If the nodal connectivity of cells is not defined.
5089  */
5090 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5091 {
5092   checkFullyDefined();
5093   bool ret=false;
5094   int nbOfCells=getNumberOfCells();
5095   for(int i=0;i<nbOfCells && !ret;i++)
5096     {
5097       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5098       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5099       ret=cm.isQuadratic();
5100     }
5101   return ret;
5102 }
5103
5104 /*!
5105  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5106  * this mesh, it remains unchanged.
5107  *  \throw If the coordinates array is not set.
5108  *  \throw If the nodal connectivity of cells is not defined.
5109  */
5110 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5111 {
5112   checkFullyDefined();
5113   int nbOfCells=getNumberOfCells();
5114   int delta=0;
5115   const int *iciptr=_nodal_connec_index->getConstPointer();
5116   for(int i=0;i<nbOfCells;i++)
5117     {
5118       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5119       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5120       if(cm.isQuadratic())
5121         {
5122           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5123           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5124           if(!cml.isDynamic())
5125             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5126           else
5127             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5128         }
5129     }
5130   if(delta==0)
5131     return ;
5132   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5133   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5134   const int *icptr=_nodal_connec->getConstPointer();
5135   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
5136   newConnI->alloc(nbOfCells+1,1);
5137   int *ocptr=newConn->getPointer();
5138   int *ociptr=newConnI->getPointer();
5139   *ociptr=0;
5140   _types.clear();
5141   for(int i=0;i<nbOfCells;i++,ociptr++)
5142     {
5143       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5144       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5145       if(!cm.isQuadratic())
5146         {
5147           _types.insert(type);
5148           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5149           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5150         }
5151       else
5152         {
5153           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5154           _types.insert(typel);
5155           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5156           int newNbOfNodes=cml.getNumberOfNodes();
5157           if(cml.isDynamic())
5158             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5159           *ocptr++=(int)typel;
5160           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5161           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5162         }
5163     }
5164   setConnectivity(newConn,newConnI,false);
5165 }
5166
5167 /*!
5168  * This method converts all linear cell in \a this to quadratic one.
5169  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5170  * 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)
5171  * 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.
5172  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5173  * end of the existing coordinates.
5174  * 
5175  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5176  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5177  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5178  * 
5179  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5180  *
5181  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5182  */
5183 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5184 {
5185   DataArrayInt *conn=0,*connI=0;
5186   DataArrayDouble *coords=0;
5187   std::set<INTERP_KERNEL::NormalizedCellType> types;
5188   checkFullyDefined();
5189   MCAuto<DataArrayInt> ret,connSafe,connISafe;
5190   MCAuto<DataArrayDouble> coordsSafe;
5191   int meshDim=getMeshDimension();
5192   switch(conversionType)
5193   {
5194     case 0:
5195       switch(meshDim)
5196       {
5197         case 1:
5198           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5199           connSafe=conn; connISafe=connI; coordsSafe=coords;
5200           break;
5201         case 2:
5202           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5203           connSafe=conn; connISafe=connI; coordsSafe=coords;
5204           break;
5205         case 3:
5206           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5207           connSafe=conn; connISafe=connI; coordsSafe=coords;
5208           break;
5209         default:
5210           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5211       }
5212       break;
5213         case 1:
5214           {
5215             switch(meshDim)
5216             {
5217               case 1:
5218                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5219                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5220                 break;
5221               case 2:
5222                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5223                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5224                 break;
5225               case 3:
5226                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5227                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5228                 break;
5229               default:
5230                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5231             }
5232             break;
5233           }
5234         default:
5235           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5236   }
5237   setConnectivity(connSafe,connISafe,false);
5238   _types=types;
5239   setCoords(coordsSafe);
5240   return ret.retn();
5241 }
5242
5243 /*!
5244  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5245  * so that the number of cells remains the same. Quadratic faces are converted to
5246  * polygons. This method works only for 2D meshes in
5247  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5248  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5249  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5250  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5251  *         a polylinized edge constituting the input polygon.
5252  *  \throw If the coordinates array is not set.
5253  *  \throw If the nodal connectivity of cells is not defined.
5254  *  \throw If \a this->getMeshDimension() != 2.
5255  *  \throw If \a this->getSpaceDimension() != 2.
5256  */
5257 void MEDCouplingUMesh::tessellate2D(double eps)
5258 {
5259   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
5260   if(spaceDim!=2)
5261     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
5262   switch(meshDim)
5263     {
5264     case 1:
5265       return tessellate2DCurveInternal(eps);
5266     case 2:
5267       return tessellate2DInternal(eps);
5268     default:
5269       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
5270     }
5271 }
5272 /*!
5273  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5274  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5275  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5276  *         a sub-divided edge.
5277  *  \throw If the coordinates array is not set.
5278  *  \throw If the nodal connectivity of cells is not defined.
5279  *  \throw If \a this->getMeshDimension() != 1.
5280  *  \throw If \a this->getSpaceDimension() != 2.
5281  */
5282
5283 #if 0
5284 /*!
5285  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5286  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5287  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5288  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5289  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5290  * This method can be seen as the opposite method of colinearize2D.
5291  * 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
5292  * to avoid to modify the numbering of existing nodes.
5293  *
5294  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5295  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5296  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5297  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5298  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5299  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5300  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5301  *
5302  * \sa buildDescendingConnectivity2
5303  */
5304 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5305                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5306 {
5307   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5308     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5309   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5310   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5311     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5312   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5313     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5314   //DataArrayInt *out0(0),*outi0(0);
5315   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5316   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
5317   //out0s=out0s->buildUnique(); out0s->sort(true);
5318 }
5319 #endif
5320
5321 /*!
5322  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5323  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5324  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5325  */
5326 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5327 {
5328   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5329   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5330   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5331   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5332   int nbOfCells=getNumberOfCells();
5333   int nbOfNodes=getNumberOfNodes();
5334   const int *cPtr=_nodal_connec->getConstPointer();
5335   const int *icPtr=_nodal_connec_index->getConstPointer();
5336   int lastVal=0,offset=nbOfNodes;
5337   for(int i=0;i<nbOfCells;i++,icPtr++)
5338     {
5339       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5340       if(type==INTERP_KERNEL::NORM_SEG2)
5341         {
5342           types.insert(INTERP_KERNEL::NORM_SEG3);
5343           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5344           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5345           newConn->pushBackSilent(offset++);
5346           lastVal+=4;
5347           newConnI->pushBackSilent(lastVal);
5348           ret->pushBackSilent(i);
5349         }
5350       else
5351         {
5352           types.insert(type);
5353           lastVal+=(icPtr[1]-icPtr[0]);
5354           newConnI->pushBackSilent(lastVal);
5355           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5356         }
5357     }
5358   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5359   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5360   return ret.retn();
5361 }
5362
5363 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
5364 {
5365   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5366   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5367   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5368   //
5369   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5370   DataArrayInt *conn1D=0,*conn1DI=0;
5371   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5372   DataArrayDouble *coordsTmp=0;
5373   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5374   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5375   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5376   const int *c1DPtr=conn1D->begin();
5377   const int *c1DIPtr=conn1DI->begin();
5378   int nbOfCells=getNumberOfCells();
5379   const int *cPtr=_nodal_connec->getConstPointer();
5380   const int *icPtr=_nodal_connec_index->getConstPointer();
5381   int lastVal=0;
5382   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5383     {
5384       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5385       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5386       if(!cm.isQuadratic())
5387         {
5388           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5389           types.insert(typ2); newConn->pushBackSilent(typ2);
5390           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5391           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5392             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5393           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5394           newConnI->pushBackSilent(lastVal);
5395           ret->pushBackSilent(i);
5396         }
5397       else
5398         {
5399           types.insert(typ);
5400           lastVal+=(icPtr[1]-icPtr[0]);
5401           newConnI->pushBackSilent(lastVal);
5402           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5403         }
5404     }
5405   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5406   return ret.retn();
5407 }
5408
5409 /*!
5410  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5411  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5412  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5413  */
5414 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5415 {
5416   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5417   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5418   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5419 }
5420
5421 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5422 {
5423   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5424   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5425   //
5426   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5427   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5428   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5429   //
5430   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5431   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5432   DataArrayInt *conn1D=0,*conn1DI=0;
5433   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5434   DataArrayDouble *coordsTmp=0;
5435   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5436   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5437   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5438   const int *c1DPtr=conn1D->begin();
5439   const int *c1DIPtr=conn1DI->begin();
5440   int nbOfCells=getNumberOfCells();
5441   const int *cPtr=_nodal_connec->getConstPointer();
5442   const int *icPtr=_nodal_connec_index->getConstPointer();
5443   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5444   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5445     {
5446       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5447       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5448       if(!cm.isQuadratic())
5449         {
5450           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5451           types.insert(typ2); newConn->pushBackSilent(typ2);
5452           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5453           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5454             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5455           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5456           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5457           newConnI->pushBackSilent(lastVal);
5458           ret->pushBackSilent(i);
5459         }
5460       else
5461         {
5462           types.insert(typ);
5463           lastVal+=(icPtr[1]-icPtr[0]);
5464           newConnI->pushBackSilent(lastVal);
5465           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5466         }
5467     }
5468   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5469   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5470   return ret.retn();
5471 }
5472
5473 /*!
5474  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5475  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5476  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5477  */
5478 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5479 {
5480   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5481   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5482   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5483 }
5484
5485 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5486 {
5487   MCAuto<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5488   MCAuto<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5489   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5490   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5491   //
5492   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5493   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5494   MCAuto<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5495   //
5496   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5497   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5498   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5499   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5500   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5501   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5502   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5503   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5504   MCAuto<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5505   MCAuto<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5506   MCAuto<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5507   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5508   int nbOfCells=getNumberOfCells();
5509   const int *cPtr=_nodal_connec->getConstPointer();
5510   const int *icPtr=_nodal_connec_index->getConstPointer();
5511   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5512   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5513     {
5514       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5515       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5516       if(!cm.isQuadratic())
5517         {
5518           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5519           if(typ2==INTERP_KERNEL::NORM_ERROR)
5520             {
5521               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5522               throw INTERP_KERNEL::Exception(oss.str());
5523             }
5524           types.insert(typ2); newConn->pushBackSilent(typ2);
5525           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5526           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5527             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5528           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5529             {
5530               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5531               int tmpPos=newConn->getNumberOfTuples();
5532               newConn->pushBackSilent(nodeId2);
5533               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5534             }
5535           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5536           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5537           newConnI->pushBackSilent(lastVal);
5538           ret->pushBackSilent(i);
5539         }
5540       else
5541         {
5542           types.insert(typ);
5543           lastVal+=(icPtr[1]-icPtr[0]);
5544           newConnI->pushBackSilent(lastVal);
5545           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5546         }
5547     }
5548   MCAuto<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5549   MCAuto<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5550   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5551   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5552   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5553   int *c=newConn->getPointer();
5554   const int *cI(newConnI->begin());
5555   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5556     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5557   offset=coordsTmp2Safe->getNumberOfTuples();
5558   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5559     c[cI[(*elt)+1]-1]+=offset;
5560   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5561   return ret.retn();
5562 }
5563
5564 /*!
5565  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5566  * In addition, returns an array mapping new cells to old ones. <br>
5567  * This method typically increases the number of cells in \a this mesh
5568  * but the number of nodes remains \b unchanged.
5569  * That's why the 3D splitting policies
5570  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5571  *  \param [in] policy - specifies a pattern used for splitting.
5572  * The semantic of \a policy is:
5573  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5574  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5575  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5576  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5577  *
5578  *
5579  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5580  *          an id of old cell producing it. The caller is to delete this array using
5581  *         decrRef() as it is no more needed.
5582  *
5583  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5584  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5585  *          and \a this->getMeshDimension() != 3. 
5586  *  \throw If \a policy is not one of the four discussed above.
5587  *  \throw If the nodal connectivity of cells is not defined.
5588  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5589  */
5590 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5591 {
5592   switch(policy)
5593   {
5594     case 0:
5595       return simplexizePol0();
5596     case 1:
5597       return simplexizePol1();
5598     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5599         return simplexizePlanarFace5();
5600     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5601         return simplexizePlanarFace6();
5602     default:
5603       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)");
5604   }
5605 }
5606
5607 /*!
5608  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5609  * - 1D: INTERP_KERNEL::NORM_SEG2
5610  * - 2D: INTERP_KERNEL::NORM_TRI3
5611  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5612  *
5613  * This method is useful for users that need to use P1 field services as
5614  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5615  * All these methods need mesh support containing only simplex cells.
5616  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5617  *  \throw If the coordinates array is not set.
5618  *  \throw If the nodal connectivity of cells is not defined.
5619  *  \throw If \a this->getMeshDimension() < 1.
5620  */
5621 bool MEDCouplingUMesh::areOnlySimplexCells() const
5622 {
5623   checkFullyDefined();
5624   int mdim=getMeshDimension();
5625   if(mdim<1 || mdim>3)
5626     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5627   int nbCells=getNumberOfCells();
5628   const int *conn=_nodal_connec->getConstPointer();
5629   const int *connI=_nodal_connec_index->getConstPointer();
5630   for(int i=0;i<nbCells;i++)
5631     {
5632       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5633       if(!cm.isSimplex())
5634         return false;
5635     }
5636   return true;
5637 }
5638
5639 /*!
5640  * This method implements policy 0 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5641  */
5642 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5643 {
5644   checkConnectivityFullyDefined();
5645   if(getMeshDimension()!=2)
5646     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5647   int nbOfCells=getNumberOfCells();
5648   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5649   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5650   ret->alloc(nbOfCells+nbOfCutCells,1);
5651   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5652   int *retPt=ret->getPointer();
5653   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5654   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5655   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5656   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5657   int *pt=newConn->getPointer();
5658   int *ptI=newConnI->getPointer();
5659   ptI[0]=0;
5660   const int *oldc=_nodal_connec->getConstPointer();
5661   const int *ci=_nodal_connec_index->getConstPointer();
5662   for(int i=0;i<nbOfCells;i++,ci++)
5663     {
5664       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5665         {
5666           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5667             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5668           pt=std::copy(tmp,tmp+8,pt);
5669           ptI[1]=ptI[0]+4;
5670           ptI[2]=ptI[0]+8;
5671           *retPt++=i;
5672           *retPt++=i;
5673           ptI+=2;
5674         }
5675       else
5676         {
5677           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5678           ptI[1]=ptI[0]+ci[1]-ci[0];
5679           ptI++;
5680           *retPt++=i;
5681         }
5682     }
5683   _nodal_connec->decrRef();
5684   _nodal_connec=newConn.retn();
5685   _nodal_connec_index->decrRef();
5686   _nodal_connec_index=newConnI.retn();
5687   computeTypes();
5688   updateTime();
5689   return ret.retn();
5690 }
5691
5692 /*!
5693  * This method implements policy 1 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5694  */
5695 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5696 {
5697   checkConnectivityFullyDefined();
5698   if(getMeshDimension()!=2)
5699     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5700   int nbOfCells=getNumberOfCells();
5701   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5702   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5703   ret->alloc(nbOfCells+nbOfCutCells,1);
5704   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5705   int *retPt=ret->getPointer();
5706   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5707   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5708   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5709   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5710   int *pt=newConn->getPointer();
5711   int *ptI=newConnI->getPointer();
5712   ptI[0]=0;
5713   const int *oldc=_nodal_connec->getConstPointer();
5714   const int *ci=_nodal_connec_index->getConstPointer();
5715   for(int i=0;i<nbOfCells;i++,ci++)
5716     {
5717       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5718         {
5719           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5720             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5721           pt=std::copy(tmp,tmp+8,pt);
5722           ptI[1]=ptI[0]+4;
5723           ptI[2]=ptI[0]+8;
5724           *retPt++=i;
5725           *retPt++=i;
5726           ptI+=2;
5727         }
5728       else
5729         {
5730           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5731           ptI[1]=ptI[0]+ci[1]-ci[0];
5732           ptI++;
5733           *retPt++=i;
5734         }
5735     }
5736   _nodal_connec->decrRef();
5737   _nodal_connec=newConn.retn();
5738   _nodal_connec_index->decrRef();
5739   _nodal_connec_index=newConnI.retn();
5740   computeTypes();
5741   updateTime();
5742   return ret.retn();
5743 }
5744
5745 /*!
5746  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5747  */
5748 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5749 {
5750   checkConnectivityFullyDefined();
5751   if(getMeshDimension()!=3)
5752     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5753   int nbOfCells=getNumberOfCells();
5754   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5755   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5756   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5757   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5758   int *retPt=ret->getPointer();
5759   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5760   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5761   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5762   newConn->alloc(getNodalConnectivityArrayLen()+16*nbOfCutCells,1);//21
5763   int *pt=newConn->getPointer();
5764   int *ptI=newConnI->getPointer();
5765   ptI[0]=0;
5766   const int *oldc=_nodal_connec->getConstPointer();
5767   const int *ci=_nodal_connec_index->getConstPointer();
5768   for(int i=0;i<nbOfCells;i++,ci++)
5769     {
5770       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5771         {
5772           for(int j=0;j<5;j++,pt+=5,ptI++)
5773             {
5774               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5775               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];
5776               *retPt++=i;
5777               ptI[1]=ptI[0]+5;
5778             }
5779         }
5780       else
5781         {
5782           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5783           ptI[1]=ptI[0]+ci[1]-ci[0];
5784           ptI++;
5785           *retPt++=i;
5786         }
5787     }
5788   _nodal_connec->decrRef();
5789   _nodal_connec=newConn.retn();
5790   _nodal_connec_index->decrRef();
5791   _nodal_connec_index=newConnI.retn();
5792   computeTypes();
5793   updateTime();
5794   return ret.retn();
5795 }
5796
5797 /*!
5798  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5799  */
5800 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5801 {
5802   checkConnectivityFullyDefined();
5803   if(getMeshDimension()!=3)
5804     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5805   int nbOfCells=getNumberOfCells();
5806   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5807   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5808   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5809   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5810   int *retPt=ret->getPointer();
5811   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5812   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5813   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5814   newConn->alloc(getNodalConnectivityArrayLen()+21*nbOfCutCells,1);
5815   int *pt=newConn->getPointer();
5816   int *ptI=newConnI->getPointer();
5817   ptI[0]=0;
5818   const int *oldc=_nodal_connec->getConstPointer();
5819   const int *ci=_nodal_connec_index->getConstPointer();
5820   for(int i=0;i<nbOfCells;i++,ci++)
5821     {
5822       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5823         {
5824           for(int j=0;j<6;j++,pt+=5,ptI++)
5825             {
5826               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5827               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];
5828               *retPt++=i;
5829               ptI[1]=ptI[0]+5;
5830             }
5831         }
5832       else
5833         {
5834           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5835           ptI[1]=ptI[0]+ci[1]-ci[0];
5836           ptI++;
5837           *retPt++=i;
5838         }
5839     }
5840   _nodal_connec->decrRef();
5841   _nodal_connec=newConn.retn();
5842   _nodal_connec_index->decrRef();
5843   _nodal_connec_index=newConnI.retn();
5844   computeTypes();
5845   updateTime();
5846   return ret.retn();
5847 }
5848
5849 /*!
5850  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5851  * so that the number of cells remains the same. Quadratic faces are converted to
5852  * polygons. This method works only for 2D meshes in
5853  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5854  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5855  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5856  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5857  *         a polylinized edge constituting the input polygon.
5858  *  \throw If the coordinates array is not set.
5859  *  \throw If the nodal connectivity of cells is not defined.
5860  *  \throw If \a this->getMeshDimension() != 2.
5861  *  \throw If \a this->getSpaceDimension() != 2.
5862  */
5863 void MEDCouplingUMesh::tessellate2DInternal(double eps)
5864 {
5865   checkFullyDefined();
5866   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5867     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5868   double epsa=fabs(eps);
5869   if(epsa<std::numeric_limits<double>::min())
5870     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 !");
5871   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
5872   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
5873   revDesc1=0; revDescIndx1=0;
5874   mDesc->tessellate2D(eps);
5875   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5876   setCoords(mDesc->getCoords());
5877 }
5878
5879 /*!
5880  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5881  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5882  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5883  *         a sub-divided edge.
5884  *  \throw If the coordinates array is not set.
5885  *  \throw If the nodal connectivity of cells is not defined.
5886  *  \throw If \a this->getMeshDimension() != 1.
5887  *  \throw If \a this->getSpaceDimension() != 2.
5888  */
5889 void MEDCouplingUMesh::tessellate2DCurveInternal(double eps)
5890 {
5891   checkFullyDefined();
5892   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5893     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5894   double epsa=fabs(eps);
5895   if(epsa<std::numeric_limits<double>::min())
5896     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 !");
5897   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5898   int nbCells=getNumberOfCells();
5899   int nbNodes=getNumberOfNodes();
5900   const int *conn=_nodal_connec->getConstPointer();
5901   const int *connI=_nodal_connec_index->getConstPointer();
5902   const double *coords=_coords->getConstPointer();
5903   std::vector<double> addCoo;
5904   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5905   MCAuto<DataArrayInt> newConnI(DataArrayInt::New());
5906   newConnI->alloc(nbCells+1,1);
5907   int *newConnIPtr=newConnI->getPointer();
5908   *newConnIPtr=0;
5909   int tmp1[3];
5910   INTERP_KERNEL::Node *tmp2[3];
5911   std::set<INTERP_KERNEL::NormalizedCellType> types;
5912   for(int i=0;i<nbCells;i++,newConnIPtr++)
5913     {
5914       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5915       if(cm.isQuadratic())
5916         {//assert(connI[i+1]-connI[i]-1==3)
5917           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5918           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5919           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5920           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5921           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5922           if(eac)
5923             {
5924               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5925               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5926               delete eac;
5927               newConnIPtr[1]=(int)newConn.size();
5928             }
5929           else
5930             {
5931               types.insert(INTERP_KERNEL::NORM_SEG2);
5932               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5933               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5934               newConnIPtr[1]=newConnIPtr[0]+3;
5935             }
5936         }
5937       else
5938         {
5939           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5940           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5941           newConnIPtr[1]=newConnIPtr[0]+3;
5942         }
5943     }
5944   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5945     return ;
5946   _types=types;
5947   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5948   MCAuto<DataArrayInt> newConnArr=DataArrayInt::New();
5949   newConnArr->alloc((int)newConn.size(),1);
5950   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5951   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5952   MCAuto<DataArrayDouble> newCoords=DataArrayDouble::New();
5953   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5954   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5955   std::copy(addCoo.begin(),addCoo.end(),work);
5956   DataArrayDouble::SetArrayIn(newCoords,_coords);
5957   updateTime();
5958 }
5959
5960 /*!
5961  * 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.
5962  * This method completly ignore coordinates.
5963  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5964  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5965  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5966  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5967  */
5968 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5969 {
5970   checkFullyDefined();
5971   if(getMeshDimension()!=2)
5972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5973   int nbOfCells=getNumberOfCells();
5974   int *connI=_nodal_connec_index->getPointer();
5975   int newConnLgth=0;
5976   for(int i=0;i<nbOfCells;i++,connI++)
5977     {
5978       int offset=descIndex[i];
5979       int nbOfEdges=descIndex[i+1]-offset;
5980       //
5981       bool ddirect=desc[offset+nbOfEdges-1]>0;
5982       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5983       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5984       for(int j=0;j<nbOfEdges;j++)
5985         {
5986           bool direct=desc[offset+j]>0;
5987           int edgeId=std::abs(desc[offset+j])-1;
5988           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5989             {
5990               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5991               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5992               int ref2=direct?id1:id2;
5993               if(ref==ref2)
5994                 {
5995                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5996                   newConnLgth+=nbOfSubNodes-1;
5997                   ref=direct?id2:id1;
5998                 }
5999               else
6000                 {
6001                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
6002                   throw INTERP_KERNEL::Exception(oss.str());
6003                 }
6004             }
6005           else
6006             {
6007               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
6008             }
6009         }
6010       newConnLgth++;//+1 is for cell type
6011       connI[1]=newConnLgth;
6012     }
6013   //
6014   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
6015   newConn->alloc(newConnLgth,1);
6016   int *work=newConn->getPointer();
6017   for(int i=0;i<nbOfCells;i++)
6018     {
6019       *work++=INTERP_KERNEL::NORM_POLYGON;
6020       int offset=descIndex[i];
6021       int nbOfEdges=descIndex[i+1]-offset;
6022       for(int j=0;j<nbOfEdges;j++)
6023         {
6024           bool direct=desc[offset+j]>0;
6025           int edgeId=std::abs(desc[offset+j])-1;
6026           if(direct)
6027             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
6028           else
6029             {
6030               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
6031               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
6032               work=std::copy(it,it+nbOfSubNodes-1,work);
6033             }
6034         }
6035     }
6036   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
6037   _types.clear();
6038   if(nbOfCells>0)
6039     _types.insert(INTERP_KERNEL::NORM_POLYGON);
6040 }
6041
6042 /*!
6043  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
6044  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
6045  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
6046  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
6047  * so it can be useful to call mergeNodes() before calling this method.
6048  *  \throw If \a this->getMeshDimension() <= 1.
6049  *  \throw If the coordinates array is not set.
6050  *  \throw If the nodal connectivity of cells is not defined.
6051  */
6052 void MEDCouplingUMesh::convertDegeneratedCells()
6053 {
6054   checkFullyDefined();
6055   if(getMeshDimension()<=1)
6056     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
6057   int nbOfCells=getNumberOfCells();
6058   if(nbOfCells<1)
6059     return ;
6060   int initMeshLgth=getNodalConnectivityArrayLen();
6061   int *conn=_nodal_connec->getPointer();
6062   int *index=_nodal_connec_index->getPointer();
6063   int posOfCurCell=0;
6064   int newPos=0;
6065   int lgthOfCurCell;
6066   for(int i=0;i<nbOfCells;i++)
6067     {
6068       lgthOfCurCell=index[i+1]-posOfCurCell;
6069       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
6070       int newLgth;
6071       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
6072                                                                                                      conn+newPos+1,newLgth);
6073       conn[newPos]=newType;
6074       newPos+=newLgth+1;
6075       posOfCurCell=index[i+1];
6076       index[i+1]=newPos;
6077     }
6078   if(newPos!=initMeshLgth)
6079     _nodal_connec->reAlloc(newPos);
6080   computeTypes();
6081 }
6082
6083 /*!
6084  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
6085  * A cell is considered to be oriented correctly if an angle between its
6086  * normal vector and a given vector is less than \c PI / \c 2.
6087  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6088  *         cells. 
6089  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6090  *         checked.
6091  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6092  *         is not cleared before filling in.
6093  *  \throw If \a this->getMeshDimension() != 2.
6094  *  \throw If \a this->getSpaceDimension() != 3.
6095  *
6096  *  \if ENABLE_EXAMPLES
6097  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6098  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6099  *  \endif
6100  */
6101 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6102 {
6103   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6104     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6105   int nbOfCells=getNumberOfCells();
6106   const int *conn=_nodal_connec->getConstPointer();
6107   const int *connI=_nodal_connec_index->getConstPointer();
6108   const double *coordsPtr=_coords->getConstPointer();
6109   for(int i=0;i<nbOfCells;i++)
6110     {
6111       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6112       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6113         {
6114           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6115           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6116             cells.push_back(i);
6117         }
6118     }
6119 }
6120
6121 /*!
6122  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6123  * considered to be oriented correctly if an angle between its normal vector and a
6124  * given vector is less than \c PI / \c 2. 
6125  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6126  *         cells. 
6127  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6128  *         checked.
6129  *  \throw If \a this->getMeshDimension() != 2.
6130  *  \throw If \a this->getSpaceDimension() != 3.
6131  *
6132  *  \if ENABLE_EXAMPLES
6133  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6134  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6135  *  \endif
6136  *
6137  *  \sa changeOrientationOfCells
6138  */
6139 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6140 {
6141   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6142     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6143   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6144   const int *connI(_nodal_connec_index->getConstPointer());
6145   const double *coordsPtr(_coords->getConstPointer());
6146   bool isModified(false);
6147   for(int i=0;i<nbOfCells;i++)
6148     {
6149       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6150       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6151         {
6152           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6153           bool isQuadratic(cm.isQuadratic());
6154           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6155             {
6156               isModified=true;
6157               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6158             }
6159         }
6160     }
6161   if(isModified)
6162     _nodal_connec->declareAsNew();
6163   updateTime();
6164 }
6165
6166 /*!
6167  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6168  *
6169  * \sa orientCorrectly2DCells
6170  */
6171 void MEDCouplingUMesh::changeOrientationOfCells()
6172 {
6173   int mdim(getMeshDimension());
6174   if(mdim!=2 && mdim!=1)
6175     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6176   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6177   const int *connI(_nodal_connec_index->getConstPointer());
6178   if(mdim==2)
6179     {//2D
6180       for(int i=0;i<nbOfCells;i++)
6181         {
6182           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6183           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6184           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6185         }
6186     }
6187   else
6188     {//1D
6189       for(int i=0;i<nbOfCells;i++)
6190         {
6191           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6192           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6193           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6194         }
6195     }
6196 }
6197
6198 /*!
6199  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6200  * oriented facets. The normal vector of the facet should point out of the cell.
6201  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6202  *         is not cleared before filling in.
6203  *  \throw If \a this->getMeshDimension() != 3.
6204  *  \throw If \a this->getSpaceDimension() != 3.
6205  *  \throw If the coordinates array is not set.
6206  *  \throw If the nodal connectivity of cells is not defined.
6207  *
6208  *  \if ENABLE_EXAMPLES
6209  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6210  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6211  *  \endif
6212  */
6213 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6214 {
6215   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6216     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6217   int nbOfCells=getNumberOfCells();
6218   const int *conn=_nodal_connec->getConstPointer();
6219   const int *connI=_nodal_connec_index->getConstPointer();
6220   const double *coordsPtr=_coords->getConstPointer();
6221   for(int i=0;i<nbOfCells;i++)
6222     {
6223       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6224       if(type==INTERP_KERNEL::NORM_POLYHED)
6225         {
6226           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6227             cells.push_back(i);
6228         }
6229     }
6230 }
6231
6232 /*!
6233  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6234  * out of the cell. 
6235  *  \throw If \a this->getMeshDimension() != 3.
6236  *  \throw If \a this->getSpaceDimension() != 3.
6237  *  \throw If the coordinates array is not set.
6238  *  \throw If the nodal connectivity of cells is not defined.
6239  *  \throw If the reparation fails.
6240  *
6241  *  \if ENABLE_EXAMPLES
6242  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6243  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6244  *  \endif
6245  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6246  */
6247 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6248 {
6249   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6250     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6251   int nbOfCells=getNumberOfCells();
6252   int *conn=_nodal_connec->getPointer();
6253   const int *connI=_nodal_connec_index->getConstPointer();
6254   const double *coordsPtr=_coords->getConstPointer();
6255   for(int i=0;i<nbOfCells;i++)
6256     {
6257       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6258       if(type==INTERP_KERNEL::NORM_POLYHED)
6259         {
6260           try
6261           {
6262               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6263                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6264           }
6265           catch(INTERP_KERNEL::Exception& e)
6266           {
6267               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6268               throw INTERP_KERNEL::Exception(oss.str());
6269           }
6270         }
6271     }
6272   updateTime();
6273 }
6274
6275 /*!
6276  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6277  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6278  * according to which the first facet of the cell should be oriented to have the normal vector
6279  * pointing out of cell.
6280  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6281  *         cells. The caller is to delete this array using decrRef() as it is no more
6282  *         needed. 
6283  *  \throw If \a this->getMeshDimension() != 3.
6284  *  \throw If \a this->getSpaceDimension() != 3.
6285  *  \throw If the coordinates array is not set.
6286  *  \throw If the nodal connectivity of cells is not defined.
6287  *
6288  *  \if ENABLE_EXAMPLES
6289  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6290  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6291  *  \endif
6292  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6293  */
6294 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6295 {
6296   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6297   if(getMeshDimension()!=3)
6298     throw INTERP_KERNEL::Exception(msg);
6299   int spaceDim=getSpaceDimension();
6300   if(spaceDim!=3)
6301     throw INTERP_KERNEL::Exception(msg);
6302   //
6303   int nbOfCells=getNumberOfCells();
6304   int *conn=_nodal_connec->getPointer();
6305   const int *connI=_nodal_connec_index->getConstPointer();
6306   const double *coo=getCoords()->getConstPointer();
6307   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6308   for(int i=0;i<nbOfCells;i++)
6309     {
6310       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6311       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6312         {
6313           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6314             {
6315               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6316               cells->pushBackSilent(i);
6317             }
6318         }
6319     }
6320   return cells.retn();
6321 }
6322
6323 /*!
6324  * This method is a faster method to correct orientation of all 3D cells in \a this.
6325  * 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.
6326  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
6327  * 
6328  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6329  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6330  */
6331 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6332 {
6333   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6334     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6335   int nbOfCells=getNumberOfCells();
6336   int *conn=_nodal_connec->getPointer();
6337   const int *connI=_nodal_connec_index->getConstPointer();
6338   const double *coordsPtr=_coords->getConstPointer();
6339   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6340   for(int i=0;i<nbOfCells;i++)
6341     {
6342       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6343       switch(type)
6344       {
6345         case INTERP_KERNEL::NORM_TETRA4:
6346           {
6347             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6348               {
6349                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6350                 ret->pushBackSilent(i);
6351               }
6352             break;
6353           }
6354         case INTERP_KERNEL::NORM_PYRA5:
6355           {
6356             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6357               {
6358                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6359                 ret->pushBackSilent(i);
6360               }
6361             break;
6362           }
6363         case INTERP_KERNEL::NORM_PENTA6:
6364         case INTERP_KERNEL::NORM_HEXA8:
6365         case INTERP_KERNEL::NORM_HEXGP12:
6366           {
6367             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6368               {
6369                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6370                 ret->pushBackSilent(i);
6371               }
6372             break;
6373           }
6374         case INTERP_KERNEL::NORM_POLYHED:
6375           {
6376             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6377               {
6378                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6379                 ret->pushBackSilent(i);
6380               }
6381             break;
6382           }
6383         default:
6384           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 !");
6385       }
6386     }
6387   updateTime();
6388   return ret.retn();
6389 }
6390
6391 /*!
6392  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6393  * If it is not the case an exception will be thrown.
6394  * This method is fast because the first cell of \a this is used to compute the plane.
6395  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6396  * \param pos output of size at least 3 used to store a point owned of searched plane.
6397  */
6398 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6399 {
6400   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6401     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6402   const int *conn=_nodal_connec->getConstPointer();
6403   const int *connI=_nodal_connec_index->getConstPointer();
6404   const double *coordsPtr=_coords->getConstPointer();
6405   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6406   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6407 }
6408
6409 /*!
6410  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6411  * cells. Currently cells of the following types are treated:
6412  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6413  * For a cell of other type an exception is thrown.
6414  * Space dimension of a 2D mesh can be either 2 or 3.
6415  * The Edge Ratio of a cell \f$t\f$ is: 
6416  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6417  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6418  *  the smallest edge lengths of \f$t\f$.
6419  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6420  *          cells and one time, lying on \a this mesh. The caller is to delete this
6421  *          field using decrRef() as it is no more needed. 
6422  *  \throw If the coordinates array is not set.
6423  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6424  *  \throw If the connectivity data array has more than one component.
6425  *  \throw If the connectivity data array has a named component.
6426  *  \throw If the connectivity index data array has more than one component.
6427  *  \throw If the connectivity index data array has a named component.
6428  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6429  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6430  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6431  */
6432 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6433 {
6434   checkConsistencyLight();
6435   int spaceDim=getSpaceDimension();
6436   int meshDim=getMeshDimension();
6437   if(spaceDim!=2 && spaceDim!=3)
6438     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6439   if(meshDim!=2 && meshDim!=3)
6440     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6441   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6442   ret->setMesh(this);
6443   int nbOfCells=getNumberOfCells();
6444   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6445   arr->alloc(nbOfCells,1);
6446   double *pt=arr->getPointer();
6447   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6448   const int *conn=_nodal_connec->getConstPointer();
6449   const int *connI=_nodal_connec_index->getConstPointer();
6450   const double *coo=_coords->getConstPointer();
6451   double tmp[12];
6452   for(int i=0;i<nbOfCells;i++,pt++)
6453     {
6454       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6455       switch(t)
6456       {
6457         case INTERP_KERNEL::NORM_TRI3:
6458           {
6459             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6460             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6461             break;
6462           }
6463         case INTERP_KERNEL::NORM_QUAD4:
6464           {
6465             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6466             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6467             break;
6468           }
6469         case INTERP_KERNEL::NORM_TETRA4:
6470           {
6471             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6472             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6473             break;
6474           }
6475         default:
6476           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6477       }
6478       conn+=connI[i+1]-connI[i];
6479     }
6480   ret->setName("EdgeRatio");
6481   ret->synchronizeTimeWithSupport();
6482   return ret.retn();
6483 }
6484
6485 /*!
6486  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6487  * cells. Currently cells of the following types are treated:
6488  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6489  * For a cell of other type an exception is thrown.
6490  * Space dimension of a 2D mesh can be either 2 or 3.
6491  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6492  *          cells and one time, lying on \a this mesh. The caller is to delete this
6493  *          field using decrRef() as it is no more needed. 
6494  *  \throw If the coordinates array is not set.
6495  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6496  *  \throw If the connectivity data array has more than one component.
6497  *  \throw If the connectivity data array has a named component.
6498  *  \throw If the connectivity index data array has more than one component.
6499  *  \throw If the connectivity index data array has a named component.
6500  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6501  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6502  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6503  */
6504 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6505 {
6506   checkConsistencyLight();
6507   int spaceDim=getSpaceDimension();
6508   int meshDim=getMeshDimension();
6509   if(spaceDim!=2 && spaceDim!=3)
6510     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6511   if(meshDim!=2 && meshDim!=3)
6512     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6513   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6514   ret->setMesh(this);
6515   int nbOfCells=getNumberOfCells();
6516   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6517   arr->alloc(nbOfCells,1);
6518   double *pt=arr->getPointer();
6519   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6520   const int *conn=_nodal_connec->getConstPointer();
6521   const int *connI=_nodal_connec_index->getConstPointer();
6522   const double *coo=_coords->getConstPointer();
6523   double tmp[12];
6524   for(int i=0;i<nbOfCells;i++,pt++)
6525     {
6526       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6527       switch(t)
6528       {
6529         case INTERP_KERNEL::NORM_TRI3:
6530           {
6531             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6532             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6533             break;
6534           }
6535         case INTERP_KERNEL::NORM_QUAD4:
6536           {
6537             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6538             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6539             break;
6540           }
6541         case INTERP_KERNEL::NORM_TETRA4:
6542           {
6543             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6544             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6545             break;
6546           }
6547         default:
6548           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6549       }
6550       conn+=connI[i+1]-connI[i];
6551     }
6552   ret->setName("AspectRatio");
6553   ret->synchronizeTimeWithSupport();
6554   return ret.retn();
6555 }
6556
6557 /*!
6558  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6559  * cells of \a this 2D mesh in 3D space. It is a measure of the "planarity" of 2D cell
6560  * in 3D space. Currently only cells of the following types are
6561  * treated: INTERP_KERNEL::NORM_QUAD4.
6562  * For a cell of other type an exception is thrown.
6563  * The warp field is computed as follows: let (a,b,c,d) be the points of the quad.
6564  * Defining
6565  * \f$t=\vec{da}\times\vec{ab}\f$,
6566  * \f$u=\vec{ab}\times\vec{bc}\f$
6567  * \f$v=\vec{bc}\times\vec{cd}\f$
6568  * \f$w=\vec{cd}\times\vec{da}\f$, the warp is defined as \f$W^3\f$ with
6569  *  \f[
6570  *     W=min(\frac{t}{|t|}\cdot\frac{v}{|v|}, \frac{u}{|u|}\cdot\frac{w}{|w|})
6571  *  \f]
6572  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6573  *          cells and one time, lying on \a this mesh. The caller is to delete this
6574  *          field using decrRef() as it is no more needed. 
6575  *  \throw If the coordinates array is not set.
6576  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6577  *  \throw If the connectivity data array has more than one component.
6578  *  \throw If the connectivity data array has a named component.
6579  *  \throw If the connectivity index data array has more than one component.
6580  *  \throw If the connectivity index data array has a named component.
6581  *  \throw If \a this->getMeshDimension() != 2.
6582  *  \throw If \a this->getSpaceDimension() != 3.
6583  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6584  */
6585 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6586 {
6587   checkConsistencyLight();
6588   int spaceDim=getSpaceDimension();
6589   int meshDim=getMeshDimension();
6590   if(spaceDim!=3)
6591     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6592   if(meshDim!=2)
6593     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6594   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6595   ret->setMesh(this);
6596   int nbOfCells=getNumberOfCells();
6597   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6598   arr->alloc(nbOfCells,1);
6599   double *pt=arr->getPointer();
6600   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6601   const int *conn=_nodal_connec->getConstPointer();
6602   const int *connI=_nodal_connec_index->getConstPointer();
6603   const double *coo=_coords->getConstPointer();
6604   double tmp[12];
6605   for(int i=0;i<nbOfCells;i++,pt++)
6606     {
6607       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6608       switch(t)
6609       {
6610         case INTERP_KERNEL::NORM_QUAD4:
6611           {
6612             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6613             *pt=INTERP_KERNEL::quadWarp(tmp);
6614             break;
6615           }
6616         default:
6617           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6618       }
6619       conn+=connI[i+1]-connI[i];
6620     }
6621   ret->setName("Warp");
6622   ret->synchronizeTimeWithSupport();
6623   return ret.retn();
6624 }
6625
6626
6627 /*!
6628  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6629  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6630  * treated: INTERP_KERNEL::NORM_QUAD4.
6631  * The skew is computed as follow for a quad with points (a,b,c,d): let
6632  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
6633  * then the skew is computed as:
6634  *  \f[
6635  *    s=\frac{u}{|u|}\cdot\frac{v}{|v|}
6636  *  \f]
6637  *
6638  * For a cell of other type an exception is thrown.
6639  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6640  *          cells and one time, lying on \a this mesh. The caller is to delete this
6641  *          field using decrRef() as it is no more needed. 
6642  *  \throw If the coordinates array is not set.
6643  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6644  *  \throw If the connectivity data array has more than one component.
6645  *  \throw If the connectivity data array has a named component.
6646  *  \throw If the connectivity index data array has more than one component.
6647  *  \throw If the connectivity index data array has a named component.
6648  *  \throw If \a this->getMeshDimension() != 2.
6649  *  \throw If \a this->getSpaceDimension() != 3.
6650  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6651  */
6652 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6653 {
6654   checkConsistencyLight();
6655   int spaceDim=getSpaceDimension();
6656   int meshDim=getMeshDimension();
6657   if(spaceDim!=3)
6658     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6659   if(meshDim!=2)
6660     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6661   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6662   ret->setMesh(this);
6663   int nbOfCells=getNumberOfCells();
6664   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6665   arr->alloc(nbOfCells,1);
6666   double *pt=arr->getPointer();
6667   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6668   const int *conn=_nodal_connec->getConstPointer();
6669   const int *connI=_nodal_connec_index->getConstPointer();
6670   const double *coo=_coords->getConstPointer();
6671   double tmp[12];
6672   for(int i=0;i<nbOfCells;i++,pt++)
6673     {
6674       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6675       switch(t)
6676       {
6677         case INTERP_KERNEL::NORM_QUAD4:
6678           {
6679             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6680             *pt=INTERP_KERNEL::quadSkew(tmp);
6681             break;
6682           }
6683         default:
6684           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6685       }
6686       conn+=connI[i+1]-connI[i];
6687     }
6688   ret->setName("Skew");
6689   ret->synchronizeTimeWithSupport();
6690   return ret.retn();
6691 }
6692
6693 /*!
6694  * 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.
6695  *
6696  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6697  *
6698  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6699  */
6700 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6701 {
6702   checkConsistencyLight();
6703   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6704   ret->setMesh(this);
6705   std::set<INTERP_KERNEL::NormalizedCellType> types;
6706   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6707   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6708   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6709   arr->alloc(nbCells,1);
6710   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6711     {
6712       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6713       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
6714       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6715     }
6716   ret->setArray(arr);
6717   ret->setName("Diameter");
6718   return ret.retn();
6719 }
6720
6721 /*!
6722  * This method aggregate the bbox of each cell and put it into bbox parameter (xmin,xmax,ymin,ymax,zmin,zmax).
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  *                         For all other cases this input parameter is ignored.
6726  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6727  * 
6728  * \throw If \a this is not fully set (coordinates and connectivity).
6729  * \throw If a cell in \a this has no valid nodeId.
6730  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6731  */
6732 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6733 {
6734   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6735   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.
6736     return getBoundingBoxForBBTreeFast();
6737   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6738     {
6739       bool presenceOfQuadratic(false);
6740       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6741         {
6742           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6743           if(cm.isQuadratic())
6744             presenceOfQuadratic=true;
6745         }
6746       if(!presenceOfQuadratic)
6747         return getBoundingBoxForBBTreeFast();
6748       if(mDim==2 && sDim==2)
6749         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6750       else
6751         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6752     }
6753   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) !");
6754 }
6755
6756 /*!
6757  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6758  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6759  * 
6760  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6761  * 
6762  * \throw If \a this is not fully set (coordinates and connectivity).
6763  * \throw If a cell in \a this has no valid nodeId.
6764  */
6765 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6766 {
6767   checkFullyDefined();
6768   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6769   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6770   double *bbox(ret->getPointer());
6771   for(int i=0;i<nbOfCells*spaceDim;i++)
6772     {
6773       bbox[2*i]=std::numeric_limits<double>::max();
6774       bbox[2*i+1]=-std::numeric_limits<double>::max();
6775     }
6776   const double *coordsPtr(_coords->getConstPointer());
6777   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6778   for(int i=0;i<nbOfCells;i++)
6779     {
6780       int offset=connI[i]+1;
6781       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6782       for(int j=0;j<nbOfNodesForCell;j++)
6783         {
6784           int nodeId=conn[offset+j];
6785           if(nodeId>=0 && nodeId<nbOfNodes)
6786             {
6787               for(int k=0;k<spaceDim;k++)
6788                 {
6789                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6790                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6791                 }
6792               kk++;
6793             }
6794         }
6795       if(kk==0)
6796         {
6797           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6798           throw INTERP_KERNEL::Exception(oss.str());
6799         }
6800     }
6801   return ret.retn();
6802 }
6803
6804 /*!
6805  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6806  * useful for 2D meshes having quadratic cells
6807  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6808  * the two extremities of the arc of circle).
6809  * 
6810  * \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)
6811  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6812  * \throw If \a this is not fully defined.
6813  * \throw If \a this is not a mesh with meshDimension equal to 2.
6814  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6815  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6816  */
6817 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6818 {
6819   checkFullyDefined();
6820   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6821   if(spaceDim!=2 || mDim!=2)
6822     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!");
6823   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6824   double *bbox(ret->getPointer());
6825   const double *coords(_coords->getConstPointer());
6826   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6827   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6828     {
6829       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6830       int sz(connI[1]-connI[0]-1);
6831       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6832       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6833       INTERP_KERNEL::QuadraticPolygon *pol(0);
6834       for(int j=0;j<sz;j++)
6835         {
6836           int nodeId(conn[*connI+1+j]);
6837           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6838         }
6839       if(!cm.isQuadratic())
6840         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6841       else
6842         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6843       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6844       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6845     }
6846   return ret.retn();
6847 }
6848
6849 /*!
6850  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6851  * useful for 2D meshes having quadratic cells
6852  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6853  * the two extremities of the arc of circle).
6854  * 
6855  * \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)
6856  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6857  * \throw If \a this is not fully defined.
6858  * \throw If \a this is not a mesh with meshDimension equal to 1.
6859  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6860  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6861  */
6862 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6863 {
6864   checkFullyDefined();
6865   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6866   if(spaceDim!=2 || mDim!=1)
6867     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!");
6868   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6869   double *bbox(ret->getPointer());
6870   const double *coords(_coords->getConstPointer());
6871   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6872   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6873     {
6874       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6875       int sz(connI[1]-connI[0]-1);
6876       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6877       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6878       INTERP_KERNEL::Edge *edge(0);
6879       for(int j=0;j<sz;j++)
6880         {
6881           int nodeId(conn[*connI+1+j]);
6882           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6883         }
6884       if(!cm.isQuadratic())
6885         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6886       else
6887         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6888       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6889       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6890     }
6891   return ret.retn();
6892 }
6893
6894 /// @cond INTERNAL
6895
6896 namespace MEDCouplingImpl
6897 {
6898   class ConnReader
6899   {
6900   public:
6901     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6902     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6903   private:
6904     const int *_conn;
6905     int _val;
6906   };
6907
6908   class ConnReader2
6909   {
6910   public:
6911     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6912     bool operator() (const int& pos) { return _conn[pos]==_val; }
6913   private:
6914     const int *_conn;
6915     int _val;
6916   };
6917 }
6918
6919 /// @endcond
6920
6921 /*!
6922  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6923  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6924  * \a this is composed in cell types.
6925  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6926  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6927  * This parameter is kept only for compatibility with other methode listed above.
6928  */
6929 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6930 {
6931   checkConnectivityFullyDefined();
6932   const int *conn=_nodal_connec->getConstPointer();
6933   const int *connI=_nodal_connec_index->getConstPointer();
6934   const int *work=connI;
6935   int nbOfCells=getNumberOfCells();
6936   std::size_t n=getAllGeoTypes().size();
6937   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6938   std::set<INTERP_KERNEL::NormalizedCellType> types;
6939   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6940     {
6941       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6942       if(types.find(typ)!=types.end())
6943         {
6944           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6945           oss << " is not contiguous !";
6946           throw INTERP_KERNEL::Exception(oss.str());
6947         }
6948       types.insert(typ);
6949       ret[3*i]=typ;
6950       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
6951       ret[3*i+1]=(int)std::distance(work,work2);
6952       work=work2;
6953     }
6954   return ret;
6955 }
6956
6957 /*!
6958  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6959  * only for types cell, type node is not managed.
6960  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6961  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6962  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6963  * If 2 or more same geometric type is in \a code and exception is thrown too.
6964  *
6965  * This method firstly checks
6966  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6967  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6968  * an exception is thrown too.
6969  * 
6970  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6971  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6972  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6973  */
6974 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6975 {
6976   if(code.empty())
6977     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6978   std::size_t sz=code.size();
6979   std::size_t n=sz/3;
6980   if(sz%3!=0)
6981     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6982   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6983   int nb=0;
6984   bool isNoPflUsed=true;
6985   for(std::size_t i=0;i<n;i++)
6986     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6987       {
6988         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6989         nb+=code[3*i+1];
6990         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6991           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6992         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6993       }
6994   if(types.size()!=n)
6995     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6996   if(isNoPflUsed)
6997     {
6998       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6999         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
7000       if(types.size()==_types.size())
7001         return 0;
7002     }
7003   MCAuto<DataArrayInt> ret=DataArrayInt::New();
7004   ret->alloc(nb,1);
7005   int *retPtr=ret->getPointer();
7006   const int *connI=_nodal_connec_index->getConstPointer();
7007   const int *conn=_nodal_connec->getConstPointer();
7008   int nbOfCells=getNumberOfCells();
7009   const int *i=connI;
7010   int kk=0;
7011   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
7012     {
7013       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
7014       int offset=(int)std::distance(connI,i);
7015       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
7016       int nbOfCellsOfCurType=(int)std::distance(i,j);
7017       if(code[3*kk+2]==-1)
7018         for(int k=0;k<nbOfCellsOfCurType;k++)
7019           *retPtr++=k+offset;
7020       else
7021         {
7022           int idInIdsPerType=code[3*kk+2];
7023           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
7024             {
7025               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
7026               if(zePfl)
7027                 {
7028                   zePfl->checkAllocated();
7029                   if(zePfl->getNumberOfComponents()==1)
7030                     {
7031                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
7032                         {
7033                           if(*k>=0 && *k<nbOfCellsOfCurType)
7034                             *retPtr=(*k)+offset;
7035                           else
7036                             {
7037                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
7038                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
7039                               throw INTERP_KERNEL::Exception(oss.str());
7040                             }
7041                         }
7042                     }
7043                   else
7044                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
7045                 }
7046               else
7047                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
7048             }
7049           else
7050             {
7051               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
7052               oss << " should be in [0," << idsPerType.size() << ") !";
7053               throw INTERP_KERNEL::Exception(oss.str());
7054             }
7055         }
7056       i=j;
7057     }
7058   return ret.retn();
7059 }
7060
7061 /*!
7062  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
7063  * 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.
7064  * 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.
7065  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
7066  * 
7067  * \param [in] profile
7068  * \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.
7069  * \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,
7070  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
7071  * \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.
7072  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
7073  * \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
7074  */
7075 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
7076 {
7077   if(!profile)
7078     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
7079   if(profile->getNumberOfComponents()!=1)
7080     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
7081   checkConnectivityFullyDefined();
7082   const int *conn=_nodal_connec->getConstPointer();
7083   const int *connI=_nodal_connec_index->getConstPointer();
7084   int nbOfCells=getNumberOfCells();
7085   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7086   std::vector<int> typeRangeVals(1);
7087   for(const int *i=connI;i!=connI+nbOfCells;)
7088     {
7089       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7090       if(std::find(types.begin(),types.end(),curType)!=types.end())
7091         {
7092           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
7093         }
7094       types.push_back(curType);
7095       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7096       typeRangeVals.push_back((int)std::distance(connI,i));
7097     }
7098   //
7099   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
7100   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
7101   MCAuto<DataArrayInt> tmp0=castArr;
7102   MCAuto<DataArrayInt> tmp1=rankInsideCast;
7103   MCAuto<DataArrayInt> tmp2=castsPresent;
7104   //
7105   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
7106   code.resize(3*nbOfCastsFinal);
7107   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
7108   std::vector< MCAuto<DataArrayInt> > idsPerType2;
7109   for(int i=0;i<nbOfCastsFinal;i++)
7110     {
7111       int castId=castsPresent->getIJ(i,0);
7112       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
7113       idsInPflPerType2.push_back(tmp3);
7114       code[3*i]=(int)types[castId];
7115       code[3*i+1]=tmp3->getNumberOfTuples();
7116       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7117       if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
7118         {
7119           tmp4->copyStringInfoFrom(*profile);
7120           idsPerType2.push_back(tmp4);
7121           code[3*i+2]=(int)idsPerType2.size()-1;
7122         }
7123       else
7124         {
7125           code[3*i+2]=-1;
7126         }
7127     }
7128   std::size_t sz2=idsInPflPerType2.size();
7129   idsInPflPerType.resize(sz2);
7130   for(std::size_t i=0;i<sz2;i++)
7131     {
7132       DataArrayInt *locDa=idsInPflPerType2[i];
7133       locDa->incrRef();
7134       idsInPflPerType[i]=locDa;
7135     }
7136   std::size_t sz=idsPerType2.size();
7137   idsPerType.resize(sz);
7138   for(std::size_t i=0;i<sz;i++)
7139     {
7140       DataArrayInt *locDa=idsPerType2[i];
7141       locDa->incrRef();
7142       idsPerType[i]=locDa;
7143     }
7144 }
7145
7146 /*!
7147  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7148  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7149  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7150  * 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.
7151  */
7152 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7153 {
7154   checkFullyDefined();
7155   nM1LevMesh->checkFullyDefined();
7156   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7157     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7158   if(_coords!=nM1LevMesh->getCoords())
7159     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7160   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
7161   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
7162   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7163   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7164   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7165   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7166   tmp->setConnectivity(tmp0,tmp1);
7167   tmp->renumberCells(ret0->getConstPointer(),false);
7168   revDesc=tmp->getNodalConnectivity();
7169   revDescIndx=tmp->getNodalConnectivityIndex();
7170   DataArrayInt *ret=0;
7171   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7172     {
7173       int tmp2;
7174       ret->getMaxValue(tmp2);
7175       ret->decrRef();
7176       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7177       throw INTERP_KERNEL::Exception(oss.str());
7178     }
7179   nM1LevMeshIds=ret;
7180   //
7181   revDesc->incrRef();
7182   revDescIndx->incrRef();
7183   ret1->incrRef();
7184   ret0->incrRef();
7185   meshnM1Old2New=ret0;
7186   return ret1;
7187 }
7188
7189 /*!
7190  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7191  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7192  * in "Old to New" mode.
7193  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7194  *          this array using decrRef() as it is no more needed.
7195  *  \throw If the nodal connectivity of cells is not defined.
7196  */
7197 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7198 {
7199   checkConnectivityFullyDefined();
7200   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7201   renumberCells(ret->getConstPointer(),false);
7202   return ret.retn();
7203 }
7204
7205 /*!
7206  * This methods checks that cells are sorted by their types.
7207  * This method makes asumption (no check) that connectivity is correctly set before calling.
7208  */
7209 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7210 {
7211   checkFullyDefined();
7212   const int *conn=_nodal_connec->getConstPointer();
7213   const int *connI=_nodal_connec_index->getConstPointer();
7214   int nbOfCells=getNumberOfCells();
7215   std::set<INTERP_KERNEL::NormalizedCellType> types;
7216   for(const int *i=connI;i!=connI+nbOfCells;)
7217     {
7218       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7219       if(types.find(curType)!=types.end())
7220         return false;
7221       types.insert(curType);
7222       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7223     }
7224   return true;
7225 }
7226
7227 /*!
7228  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7229  * The geometric type order is specified by MED file.
7230  * 
7231  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7232  */
7233 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7234 {
7235   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7236 }
7237
7238 /*!
7239  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7240  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7241  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7242  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7243  */
7244 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7245 {
7246   checkFullyDefined();
7247   const int *conn=_nodal_connec->getConstPointer();
7248   const int *connI=_nodal_connec_index->getConstPointer();
7249   int nbOfCells=getNumberOfCells();
7250   if(nbOfCells==0)
7251     return true;
7252   int lastPos=-1;
7253   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7254   for(const int *i=connI;i!=connI+nbOfCells;)
7255     {
7256       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7257       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7258       if(isTypeExists!=orderEnd)
7259         {
7260           int pos=(int)std::distance(orderBg,isTypeExists);
7261           if(pos<=lastPos)
7262             return false;
7263           lastPos=pos;
7264           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7265         }
7266       else
7267         {
7268           if(sg.find(curType)==sg.end())
7269             {
7270               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7271               sg.insert(curType);
7272             }
7273           else
7274             return false;
7275         }
7276     }
7277   return true;
7278 }
7279
7280 /*!
7281  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7282  * 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
7283  * 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'.
7284  */
7285 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7286 {
7287   checkConnectivityFullyDefined();
7288   int nbOfCells=getNumberOfCells();
7289   const int *conn=_nodal_connec->getConstPointer();
7290   const int *connI=_nodal_connec_index->getConstPointer();
7291   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
7292   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
7293   tmpa->alloc(nbOfCells,1);
7294   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7295   tmpb->fillWithZero();
7296   int *tmp=tmpa->getPointer();
7297   int *tmp2=tmpb->getPointer();
7298   for(const int *i=connI;i!=connI+nbOfCells;i++)
7299     {
7300       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7301       if(where!=orderEnd)
7302         {
7303           int pos=(int)std::distance(orderBg,where);
7304           tmp2[pos]++;
7305           tmp[std::distance(connI,i)]=pos;
7306         }
7307       else
7308         {
7309           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7310           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7311           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7312           throw INTERP_KERNEL::Exception(oss.str());
7313         }
7314     }
7315   nbPerType=tmpb.retn();
7316   return tmpa.retn();
7317 }
7318
7319 /*!
7320  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7321  *
7322  * \return a new object containing the old to new correspondance.
7323  *
7324  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7325  */
7326 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7327 {
7328   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7329 }
7330
7331 /*!
7332  * 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.
7333  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7334  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7335  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7336  */
7337 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7338 {
7339   DataArrayInt *nbPerType=0;
7340   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7341   nbPerType->decrRef();
7342   return tmpa->buildPermArrPerLevel();
7343 }
7344
7345 /*!
7346  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7347  * The number of cells remains unchanged after the call of this method.
7348  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7349  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7350  *
7351  * \return the array giving the correspondance old to new.
7352  */
7353 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7354 {
7355   checkFullyDefined();
7356   computeTypes();
7357   const int *conn=_nodal_connec->getConstPointer();
7358   const int *connI=_nodal_connec_index->getConstPointer();
7359   int nbOfCells=getNumberOfCells();
7360   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7361   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7362     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7363       {
7364         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7365         types.push_back(curType);
7366         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7367       }
7368   DataArrayInt *ret=DataArrayInt::New();
7369   ret->alloc(nbOfCells,1);
7370   int *retPtr=ret->getPointer();
7371   std::fill(retPtr,retPtr+nbOfCells,-1);
7372   int newCellId=0;
7373   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7374     {
7375       for(const int *i=connI;i!=connI+nbOfCells;i++)
7376         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7377           retPtr[std::distance(connI,i)]=newCellId++;
7378     }
7379   renumberCells(retPtr,false);
7380   return ret;
7381 }
7382
7383 /*!
7384  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7385  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7386  * This method makes asumption that connectivity is correctly set before calling.
7387  */
7388 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7389 {
7390   checkConnectivityFullyDefined();
7391   const int *conn=_nodal_connec->getConstPointer();
7392   const int *connI=_nodal_connec_index->getConstPointer();
7393   int nbOfCells=getNumberOfCells();
7394   std::vector<MEDCouplingUMesh *> ret;
7395   for(const int *i=connI;i!=connI+nbOfCells;)
7396     {
7397       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7398       int beginCellId=(int)std::distance(connI,i);
7399       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7400       int endCellId=(int)std::distance(connI,i);
7401       int sz=endCellId-beginCellId;
7402       int *cells=new int[sz];
7403       for(int j=0;j<sz;j++)
7404         cells[j]=beginCellId+j;
7405       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7406       delete [] cells;
7407       ret.push_back(m);
7408     }
7409   return ret;
7410 }
7411
7412 /*!
7413  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7414  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7415  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7416  *
7417  * \return a newly allocated instance, that the caller must manage.
7418  * \throw If \a this contains more than one geometric type.
7419  * \throw If the nodal connectivity of \a this is not fully defined.
7420  * \throw If the internal data is not coherent.
7421  */
7422 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7423 {
7424   checkConnectivityFullyDefined();
7425   if(_types.size()!=1)
7426     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7427   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7428   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7429   ret->setCoords(getCoords());
7430   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7431   if(retC)
7432     {
7433       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7434       retC->setNodalConnectivity(c);
7435     }
7436   else
7437     {
7438       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7439       if(!retD)
7440         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7441       DataArrayInt *c=0,*ci=0;
7442       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7443       MCAuto<DataArrayInt> cs(c),cis(ci);
7444       retD->setNodalConnectivity(cs,cis);
7445     }
7446   return ret.retn();
7447 }
7448
7449 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7450 {
7451   checkConnectivityFullyDefined();
7452   if(_types.size()!=1)
7453     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7454   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7455   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7456   if(cm.isDynamic())
7457     {
7458       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7459       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7460       throw INTERP_KERNEL::Exception(oss.str());
7461     }
7462   int nbCells=getNumberOfCells();
7463   int typi=(int)typ;
7464   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7465   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7466   int *outPtr=connOut->getPointer();
7467   const int *conn=_nodal_connec->begin();
7468   const int *connI=_nodal_connec_index->begin();
7469   nbNodesPerCell++;
7470   for(int i=0;i<nbCells;i++,connI++)
7471     {
7472       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7473         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7474       else
7475         {
7476           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 << ") !";
7477           throw INTERP_KERNEL::Exception(oss.str());
7478         }
7479     }
7480   return connOut.retn();
7481 }
7482
7483 /*!
7484  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7485  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7486  * \param nodalConn
7487  * \param nodalConnI
7488  */
7489 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7490 {
7491   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
7492   checkConnectivityFullyDefined();
7493   if(_types.size()!=1)
7494     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7495   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7496   if(lgth<nbCells)
7497     throw INTERP_KERNEL::Exception(msg0);
7498   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7499   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7500   int *cp(c->getPointer()),*cip(ci->getPointer());
7501   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7502   cip[0]=0;
7503   for(int i=0;i<nbCells;i++,cip++,incip++)
7504     {
7505       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7506       int delta(stop-strt);
7507       if(delta>=1)
7508         {
7509           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7510             cp=std::copy(incp+strt,incp+stop,cp);
7511           else
7512             throw INTERP_KERNEL::Exception(msg0);
7513         }
7514       else
7515         throw INTERP_KERNEL::Exception(msg0);
7516       cip[1]=cip[0]+delta;
7517     }
7518   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7519 }
7520
7521 /*!
7522  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7523  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7524  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7525  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7526  * are not used here to avoid the build of big permutation array.
7527  *
7528  * \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
7529  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7530  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7531  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7532  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7533  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7534  * \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
7535  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7536  */
7537 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7538                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7539                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7540 {
7541   std::vector<const MEDCouplingUMesh *> ms2;
7542   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7543     if(*it)
7544       {
7545         (*it)->checkConnectivityFullyDefined();
7546         ms2.push_back(*it);
7547       }
7548   if(ms2.empty())
7549     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7550   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7551   int meshDim=ms2[0]->getMeshDimension();
7552   std::vector<const MEDCouplingUMesh *> m1ssm;
7553   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
7554   //
7555   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7556   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
7557   int fake=0,rk=0;
7558   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7559   ret1->alloc(0,1); ret2->alloc(0,1);
7560   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7561     {
7562       if(meshDim!=(*it)->getMeshDimension())
7563         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7564       if(refCoo!=(*it)->getCoords())
7565         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7566       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7567       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7568       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
7569       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7570         {
7571           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7572           m1ssmSingleAuto.push_back(singleCell);
7573           m1ssmSingle.push_back(singleCell);
7574           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7575         }
7576     }
7577   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7578   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7579   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7580   for(std::size_t i=0;i<m1ssm.size();i++)
7581     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7582   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7583   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7584   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7585   return ret0.retn();
7586 }
7587
7588 /*!
7589  * This method returns a newly created DataArrayInt instance.
7590  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7591  */
7592 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7593 {
7594   checkFullyDefined();
7595   const int *conn=_nodal_connec->getConstPointer();
7596   const int *connIndex=_nodal_connec_index->getConstPointer();
7597   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7598   for(const int *w=begin;w!=end;w++)
7599     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7600       ret->pushBackSilent(*w);
7601   return ret.retn();
7602 }
7603
7604 /*!
7605  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7606  * are in [0:getNumberOfCells())
7607  */
7608 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7609 {
7610   checkFullyDefined();
7611   const int *conn=_nodal_connec->getConstPointer();
7612   const int *connI=_nodal_connec_index->getConstPointer();
7613   int nbOfCells=getNumberOfCells();
7614   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7615   int *tmp=new int[nbOfCells];
7616   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7617     {
7618       int j=0;
7619       for(const int *i=connI;i!=connI+nbOfCells;i++)
7620         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7621           tmp[std::distance(connI,i)]=j++;
7622     }
7623   DataArrayInt *ret=DataArrayInt::New();
7624   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7625   ret->copyStringInfoFrom(*da);
7626   int *retPtr=ret->getPointer();
7627   const int *daPtr=da->getConstPointer();
7628   int nbOfElems=da->getNbOfElems();
7629   for(int k=0;k<nbOfElems;k++)
7630     retPtr[k]=tmp[daPtr[k]];
7631   delete [] tmp;
7632   return ret;
7633 }
7634
7635 /*!
7636  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7637  * This method \b works \b for mesh sorted by type.
7638  * cells whose ids is in 'idsPerGeoType' array.
7639  * This method conserves coords and name of mesh.
7640  */
7641 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7642 {
7643   std::vector<int> code=getDistributionOfTypes();
7644   std::size_t nOfTypesInThis=code.size()/3;
7645   int sz=0,szOfType=0;
7646   for(std::size_t i=0;i<nOfTypesInThis;i++)
7647     {
7648       if(code[3*i]!=type)
7649         sz+=code[3*i+1];
7650       else
7651         szOfType=code[3*i+1];
7652     }
7653   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7654     if(*work<0 || *work>=szOfType)
7655       {
7656         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7657         oss << ". It should be in [0," << szOfType << ") !";
7658         throw INTERP_KERNEL::Exception(oss.str());
7659       }
7660   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7661   int *idsPtr=idsTokeep->getPointer();
7662   int offset=0;
7663   for(std::size_t i=0;i<nOfTypesInThis;i++)
7664     {
7665       if(code[3*i]!=type)
7666         for(int j=0;j<code[3*i+1];j++)
7667           *idsPtr++=offset+j;
7668       else
7669         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7670       offset+=code[3*i+1];
7671     }
7672   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7673   ret->copyTinyInfoFrom(this);
7674   return ret.retn();
7675 }
7676
7677 /*!
7678  * This method returns a vector of size 'this->getNumberOfCells()'.
7679  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7680  */
7681 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7682 {
7683   int ncell=getNumberOfCells();
7684   std::vector<bool> ret(ncell);
7685   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7686   const int *c=getNodalConnectivity()->getConstPointer();
7687   for(int i=0;i<ncell;i++)
7688     {
7689       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7690       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7691       ret[i]=cm.isQuadratic();
7692     }
7693   return ret;
7694 }
7695
7696 /*!
7697  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7698  */
7699 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7700 {
7701   if(other->getType()!=UNSTRUCTURED)
7702     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7703   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7704   return MergeUMeshes(this,otherC);
7705 }
7706
7707 /*!
7708  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7709  * computed by averaging coordinates of cell nodes, so this method is not a right
7710  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7711  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7712  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7713  *          components. The caller is to delete this array using decrRef() as it is
7714  *          no more needed.
7715  *  \throw If the coordinates array is not set.
7716  *  \throw If the nodal connectivity of cells is not defined.
7717  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7718  */
7719 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
7720 {
7721   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7722   int spaceDim=getSpaceDimension();
7723   int nbOfCells=getNumberOfCells();
7724   ret->alloc(nbOfCells,spaceDim);
7725   ret->copyStringInfoFrom(*getCoords());
7726   double *ptToFill=ret->getPointer();
7727   const int *nodal=_nodal_connec->getConstPointer();
7728   const int *nodalI=_nodal_connec_index->getConstPointer();
7729   const double *coor=_coords->getConstPointer();
7730   for(int i=0;i<nbOfCells;i++)
7731     {
7732       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7733       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7734       ptToFill+=spaceDim;
7735     }
7736   return ret.retn();
7737 }
7738
7739 /*!
7740  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7741  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
7742  * 
7743  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7744  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7745  * 
7746  * \sa MEDCouplingUMesh::computeCellCenterOfMass
7747  * \throw If \a this is not fully defined (coordinates and connectivity)
7748  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7749  */
7750 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7751 {
7752   checkFullyDefined();
7753   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7754   int spaceDim=getSpaceDimension();
7755   int nbOfCells=getNumberOfCells();
7756   int nbOfNodes=getNumberOfNodes();
7757   ret->alloc(nbOfCells,spaceDim);
7758   double *ptToFill=ret->getPointer();
7759   const int *nodal=_nodal_connec->getConstPointer();
7760   const int *nodalI=_nodal_connec_index->getConstPointer();
7761   const double *coor=_coords->getConstPointer();
7762   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7763     {
7764       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7765       std::fill(ptToFill,ptToFill+spaceDim,0.);
7766       if(type!=INTERP_KERNEL::NORM_POLYHED)
7767         {
7768           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7769             {
7770               if(*conn>=0 && *conn<nbOfNodes)
7771                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7772               else
7773                 {
7774                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7775                   throw INTERP_KERNEL::Exception(oss.str());
7776                 }
7777             }
7778           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7779           if(nbOfNodesInCell>0)
7780             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7781           else
7782             {
7783               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7784               throw INTERP_KERNEL::Exception(oss.str());
7785             }
7786         }
7787       else
7788         {
7789           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7790           s.erase(-1);
7791           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7792             {
7793               if(*it>=0 && *it<nbOfNodes)
7794                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7795               else
7796                 {
7797                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7798                   throw INTERP_KERNEL::Exception(oss.str());
7799                 }
7800             }
7801           if(!s.empty())
7802             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7803           else
7804             {
7805               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7806               throw INTERP_KERNEL::Exception(oss.str());
7807             }
7808         }
7809     }
7810   return ret.retn();
7811 }
7812
7813 /*!
7814  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7815  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7816  * are specified via an array of cell ids. 
7817  *  \warning Validity of the specified cell ids is not checked! 
7818  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7819  *  \param [in] begin - an array of cell ids of interest.
7820  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7821  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7822  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7823  *          caller is to delete this array using decrRef() as it is no more needed. 
7824  *  \throw If the coordinates array is not set.
7825  *  \throw If the nodal connectivity of cells is not defined.
7826  *
7827  *  \if ENABLE_EXAMPLES
7828  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7829  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7830  *  \endif
7831  */
7832 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7833 {
7834   DataArrayDouble *ret=DataArrayDouble::New();
7835   int spaceDim=getSpaceDimension();
7836   int nbOfTuple=(int)std::distance(begin,end);
7837   ret->alloc(nbOfTuple,spaceDim);
7838   double *ptToFill=ret->getPointer();
7839   double *tmp=new double[spaceDim];
7840   const int *nodal=_nodal_connec->getConstPointer();
7841   const int *nodalI=_nodal_connec_index->getConstPointer();
7842   const double *coor=_coords->getConstPointer();
7843   for(const int *w=begin;w!=end;w++)
7844     {
7845       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7846       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7847       ptToFill+=spaceDim;
7848     }
7849   delete [] tmp;
7850   return ret;
7851 }
7852
7853 /*!
7854  * 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".
7855  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7856  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7857  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7858  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7859  * 
7860  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7861  * \throw If spaceDim!=3 or meshDim!=2.
7862  * \throw If connectivity of \a this is invalid.
7863  * \throw If connectivity of a cell in \a this points to an invalid node.
7864  */
7865 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7866 {
7867   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
7868   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7869   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7870     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7871   ret->alloc(nbOfCells,4);
7872   double *retPtr(ret->getPointer());
7873   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7874   const double *coor(_coords->begin());
7875   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7876     {
7877       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7878       if(nodalI[1]-nodalI[0]>=3)
7879         {
7880           for(int j=0;j<3;j++)
7881             {
7882               int nodeId(nodal[nodalI[0]+1+j]);
7883               if(nodeId>=0 && nodeId<nbOfNodes)
7884                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7885               else
7886                 {
7887                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7888                   throw INTERP_KERNEL::Exception(oss.str());
7889                 }
7890             }
7891         }
7892       else
7893         {
7894           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7895           throw INTERP_KERNEL::Exception(oss.str());
7896         }
7897       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7898       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7899     }
7900   return ret.retn();
7901 }
7902
7903 /*!
7904  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7905  * 
7906  */
7907 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7908 {
7909   if(!da)
7910     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7911   da->checkAllocated();
7912   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7913   ret->setCoords(da);
7914   int nbOfTuples=da->getNumberOfTuples();
7915   MCAuto<DataArrayInt> c=DataArrayInt::New();
7916   MCAuto<DataArrayInt> cI=DataArrayInt::New();
7917   c->alloc(2*nbOfTuples,1);
7918   cI->alloc(nbOfTuples+1,1);
7919   int *cp=c->getPointer();
7920   int *cip=cI->getPointer();
7921   *cip++=0;
7922   for(int i=0;i<nbOfTuples;i++)
7923     {
7924       *cp++=INTERP_KERNEL::NORM_POINT1;
7925       *cp++=i;
7926       *cip++=2*(i+1);
7927     }
7928   ret->setConnectivity(c,cI,true);
7929   return ret.retn();
7930 }
7931 /*!
7932  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7933  * Cells and nodes of
7934  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7935  *  \param [in] mesh1 - the first mesh.
7936  *  \param [in] mesh2 - the second mesh.
7937  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7938  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7939  *          is no more needed.
7940  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7941  *  \throw If the coordinates array is not set in none of the meshes.
7942  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7943  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7944  */
7945 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7946 {
7947   std::vector<const MEDCouplingUMesh *> tmp(2);
7948   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7949   return MergeUMeshes(tmp);
7950 }
7951
7952 /*!
7953  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7954  * Cells and nodes of
7955  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7956  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7957  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7958  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7959  *          is no more needed.
7960  *  \throw If \a a.size() == 0.
7961  *  \throw If \a a[ *i* ] == NULL.
7962  *  \throw If the coordinates array is not set in none of the meshes.
7963  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7964  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7965  */
7966 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7967 {
7968   std::size_t sz=a.size();
7969   if(sz==0)
7970     return MergeUMeshesLL(a);
7971   for(std::size_t ii=0;ii<sz;ii++)
7972     if(!a[ii])
7973       {
7974         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7975         throw INTERP_KERNEL::Exception(oss.str());
7976       }
7977   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
7978   std::vector< const MEDCouplingUMesh * > aa(sz);
7979   int spaceDim=-3;
7980   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7981     {
7982       const MEDCouplingUMesh *cur=a[i];
7983       const DataArrayDouble *coo=cur->getCoords();
7984       if(coo)
7985         spaceDim=coo->getNumberOfComponents();
7986     }
7987   if(spaceDim==-3)
7988     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7989   for(std::size_t i=0;i<sz;i++)
7990     {
7991       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7992       aa[i]=bb[i];
7993     }
7994   return MergeUMeshesLL(aa);
7995 }
7996
7997 /// @cond INTERNAL
7998
7999 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
8000 {
8001   if(a.empty())
8002     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
8003   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
8004   int meshDim=(*it)->getMeshDimension();
8005   int nbOfCells=(*it)->getNumberOfCells();
8006   int meshLgth=(*it++)->getNodalConnectivityArrayLen();
8007   for(;it!=a.end();it++)
8008     {
8009       if(meshDim!=(*it)->getMeshDimension())
8010         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
8011       nbOfCells+=(*it)->getNumberOfCells();
8012       meshLgth+=(*it)->getNodalConnectivityArrayLen();
8013     }
8014   std::vector<const MEDCouplingPointSet *> aps(a.size());
8015   std::copy(a.begin(),a.end(),aps.begin());
8016   MCAuto<DataArrayDouble> pts=MergeNodesArray(aps);
8017   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
8018   ret->setCoords(pts);
8019   MCAuto<DataArrayInt> c=DataArrayInt::New();
8020   c->alloc(meshLgth,1);
8021   int *cPtr=c->getPointer();
8022   MCAuto<DataArrayInt> cI=DataArrayInt::New();
8023   cI->alloc(nbOfCells+1,1);
8024   int *cIPtr=cI->getPointer();
8025   *cIPtr++=0;
8026   int offset=0;
8027   int offset2=0;
8028   for(it=a.begin();it!=a.end();it++)
8029     {
8030       int curNbOfCell=(*it)->getNumberOfCells();
8031       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
8032       const int *curC=(*it)->_nodal_connec->getConstPointer();
8033       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
8034       for(int j=0;j<curNbOfCell;j++)
8035         {
8036           const int *src=curC+curCI[j];
8037           *cPtr++=*src++;
8038           for(;src!=curC+curCI[j+1];src++,cPtr++)
8039             {
8040               if(*src!=-1)
8041                 *cPtr=*src+offset2;
8042               else
8043                 *cPtr=-1;
8044             }
8045         }
8046       offset+=curCI[curNbOfCell];
8047       offset2+=(*it)->getNumberOfNodes();
8048     }
8049   //
8050   ret->setConnectivity(c,cI,true);
8051   return ret.retn();
8052 }
8053
8054 /// @endcond
8055
8056 /*!
8057  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
8058  * dimension and sharing the node coordinates array.
8059  * All cells of the first mesh precede all cells of the second mesh
8060  * within the result mesh. 
8061  *  \param [in] mesh1 - the first mesh.
8062  *  \param [in] mesh2 - the second mesh.
8063  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8064  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8065  *          is no more needed.
8066  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
8067  *  \throw If the meshes do not share the node coordinates array.
8068  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
8069  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
8070  */
8071 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
8072 {
8073   std::vector<const MEDCouplingUMesh *> tmp(2);
8074   tmp[0]=mesh1; tmp[1]=mesh2;
8075   return MergeUMeshesOnSameCoords(tmp);
8076 }
8077
8078 /*!
8079  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8080  * dimension and sharing the node coordinates array.
8081  * All cells of the *i*-th mesh precede all cells of the
8082  * (*i*+1)-th mesh within the result mesh.
8083  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8084  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8085  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8086  *          is no more needed.
8087  *  \throw If \a a.size() == 0.
8088  *  \throw If \a a[ *i* ] == NULL.
8089  *  \throw If the meshes do not share the node coordinates array.
8090  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
8091  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
8092  */
8093 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
8094 {
8095   if(meshes.empty())
8096     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
8097   for(std::size_t ii=0;ii<meshes.size();ii++)
8098     if(!meshes[ii])
8099       {
8100         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
8101         throw INTERP_KERNEL::Exception(oss.str());
8102       }
8103   const DataArrayDouble *coords=meshes.front()->getCoords();
8104   int meshDim=meshes.front()->getMeshDimension();
8105   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
8106   int meshLgth=0;
8107   int meshIndexLgth=0;
8108   for(;iter!=meshes.end();iter++)
8109     {
8110       if(coords!=(*iter)->getCoords())
8111         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8112       if(meshDim!=(*iter)->getMeshDimension())
8113         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8114       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
8115       meshIndexLgth+=(*iter)->getNumberOfCells();
8116     }
8117   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
8118   nodal->alloc(meshLgth,1);
8119   int *nodalPtr=nodal->getPointer();
8120   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
8121   nodalIndex->alloc(meshIndexLgth+1,1);
8122   int *nodalIndexPtr=nodalIndex->getPointer();
8123   int offset=0;
8124   for(iter=meshes.begin();iter!=meshes.end();iter++)
8125     {
8126       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8127       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8128       int nbOfCells=(*iter)->getNumberOfCells();
8129       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
8130       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8131       if(iter!=meshes.begin())
8132         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8133       else
8134         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8135       offset+=meshLgth2;
8136     }
8137   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8138   ret->setName("merge");
8139   ret->setMeshDimension(meshDim);
8140   ret->setConnectivity(nodal,nodalIndex,true);
8141   ret->setCoords(coords);
8142   return ret;
8143 }
8144
8145 /*!
8146  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8147  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8148  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8149  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8150  * New" mode are returned for each input mesh.
8151  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8152  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8153  *          valid values [0,1,2], see zipConnectivityTraducer().
8154  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8155  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8156  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8157  *          no more needed.
8158  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8159  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8160  *          is no more needed.
8161  *  \throw If \a meshes.size() == 0.
8162  *  \throw If \a meshes[ *i* ] == NULL.
8163  *  \throw If the meshes do not share the node coordinates array.
8164  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8165  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8166  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8167  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8168  */
8169 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8170 {
8171   //All checks are delegated to MergeUMeshesOnSameCoords
8172   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8173   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8174   corr.resize(meshes.size());
8175   std::size_t nbOfMeshes=meshes.size();
8176   int offset=0;
8177   const int *o2nPtr=o2n->getConstPointer();
8178   for(std::size_t i=0;i<nbOfMeshes;i++)
8179     {
8180       DataArrayInt *tmp=DataArrayInt::New();
8181       int curNbOfCells=meshes[i]->getNumberOfCells();
8182       tmp->alloc(curNbOfCells,1);
8183       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8184       offset+=curNbOfCells;
8185       tmp->setName(meshes[i]->getName());
8186       corr[i]=tmp;
8187     }
8188   return ret.retn();
8189 }
8190
8191 /*!
8192  * Makes all given meshes share the nodal connectivity array. The common connectivity
8193  * array is created by concatenating the connectivity arrays of all given meshes. All
8194  * the given meshes must be of the same space dimension but dimension of cells **can
8195  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8196  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8197  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8198  *  \param [in,out] meshes - a vector of meshes to update.
8199  *  \throw If any of \a meshes is NULL.
8200  *  \throw If the coordinates array is not set in any of \a meshes.
8201  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8202  *  \throw If \a meshes are of different space dimension.
8203  */
8204 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8205 {
8206   std::size_t sz=meshes.size();
8207   if(sz==0 || sz==1)
8208     return;
8209   std::vector< const DataArrayDouble * > coords(meshes.size());
8210   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8211   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8212     {
8213       if((*it))
8214         {
8215           (*it)->checkConnectivityFullyDefined();
8216           const DataArrayDouble *coo=(*it)->getCoords();
8217           if(coo)
8218             *it2=coo;
8219           else
8220             {
8221               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8222               oss << " has no coordinate array defined !";
8223               throw INTERP_KERNEL::Exception(oss.str());
8224             }
8225         }
8226       else
8227         {
8228           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8229           oss << " is null !";
8230           throw INTERP_KERNEL::Exception(oss.str());
8231         }
8232     }
8233   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8234   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8235   int offset=(*it)->getNumberOfNodes();
8236   (*it++)->setCoords(res);
8237   for(;it!=meshes.end();it++)
8238     {
8239       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8240       (*it)->setCoords(res);
8241       (*it)->shiftNodeNumbersInConn(offset);
8242       offset+=oldNumberOfNodes;
8243     }
8244 }
8245
8246 /*!
8247  * Merges nodes coincident with a given precision within all given meshes that share
8248  * the nodal connectivity array. The given meshes **can be of different** mesh
8249  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8250  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8251  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8252  *  \param [in,out] meshes - a vector of meshes to update.
8253  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8254  *  \throw If any of \a meshes is NULL.
8255  *  \throw If the \a meshes do not share the same node coordinates array.
8256  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8257  */
8258 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8259 {
8260   if(meshes.empty())
8261     return ;
8262   std::set<const DataArrayDouble *> s;
8263   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8264     {
8265       if(*it)
8266         s.insert((*it)->getCoords());
8267       else
8268         {
8269           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 !";
8270           throw INTERP_KERNEL::Exception(oss.str());
8271         }
8272     }
8273   if(s.size()!=1)
8274     {
8275       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 !";
8276       throw INTERP_KERNEL::Exception(oss.str());
8277     }
8278   const DataArrayDouble *coo=*(s.begin());
8279   if(!coo)
8280     return;
8281   //
8282   DataArrayInt *comm,*commI;
8283   coo->findCommonTuples(eps,-1,comm,commI);
8284   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
8285   int oldNbOfNodes=coo->getNumberOfTuples();
8286   int newNbOfNodes;
8287   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8288   if(oldNbOfNodes==newNbOfNodes)
8289     return ;
8290   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8291   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8292     {
8293       (*it)->renumberNodesInConn(o2n->getConstPointer());
8294       (*it)->setCoords(newCoords);
8295     } 
8296 }
8297
8298 /*!
8299  * 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.
8300  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8301  * \param isQuad specifies the policy of connectivity.
8302  * @ret in/out parameter in which the result will be append
8303  */
8304 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8305 {
8306   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8307   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8308   ret.push_back(cm.getExtrudedType());
8309   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8310   switch(flatType)
8311   {
8312     case INTERP_KERNEL::NORM_POINT1:
8313       {
8314         ret.push_back(connBg[1]);
8315         ret.push_back(connBg[1]+nbOfNodesPerLev);
8316         break;
8317       }
8318     case INTERP_KERNEL::NORM_SEG2:
8319       {
8320         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8321         ret.insert(ret.end(),conn,conn+4);
8322         break;
8323       }
8324     case INTERP_KERNEL::NORM_SEG3:
8325       {
8326         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8327         ret.insert(ret.end(),conn,conn+8);
8328         break;
8329       }
8330     case INTERP_KERNEL::NORM_QUAD4:
8331       {
8332         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8333         ret.insert(ret.end(),conn,conn+8);
8334         break;
8335       }
8336     case INTERP_KERNEL::NORM_TRI3:
8337       {
8338         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8339         ret.insert(ret.end(),conn,conn+6);
8340         break;
8341       }
8342     case INTERP_KERNEL::NORM_TRI6:
8343       {
8344         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,
8345           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8346         ret.insert(ret.end(),conn,conn+15);
8347         break;
8348       }
8349     case INTERP_KERNEL::NORM_QUAD8:
8350       {
8351         int conn[20]={
8352           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8353           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8354           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8355         };
8356         ret.insert(ret.end(),conn,conn+20);
8357         break;
8358       }
8359     case INTERP_KERNEL::NORM_POLYGON:
8360       {
8361         std::back_insert_iterator< std::vector<int> > ii(ret);
8362         std::copy(connBg+1,connEnd,ii);
8363         *ii++=-1;
8364         std::reverse_iterator<const int *> rConnBg(connEnd);
8365         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8366         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8367         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8368         for(std::size_t i=0;i<nbOfRadFaces;i++)
8369           {
8370             *ii++=-1;
8371             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8372             std::copy(conn,conn+4,ii);
8373           }
8374         break;
8375       }
8376     default:
8377       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8378   }
8379 }
8380
8381 /*!
8382  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8383  */
8384 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8385 {
8386   std::size_t i, ip1;
8387   double v[3]={0.,0.,0.};
8388   std::size_t sz=std::distance(begin,end);
8389   if(isQuadratic)
8390     sz/=2;
8391   for(i=0;i<sz;i++)
8392     {
8393       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];
8394       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8395       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8396     }
8397   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8398
8399   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8400   // SEG3 forming a circle):
8401   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8402     {
8403       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8404       for(std::size_t j=0;j<sz;j++)
8405         {
8406           if (j%2)  // current point i is quadratic, next point i+1 is standard
8407             {
8408               i = sz+j;
8409               ip1 = (j+1)%sz; // ip1 = "i+1"
8410             }
8411           else      // current point i is standard, next point i+1 is quadratic
8412             {
8413               i = j;
8414               ip1 = j+sz;
8415             }
8416           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8417           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8418           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8419         }
8420       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8421     }
8422   return (ret>0.);
8423 }
8424
8425 /*!
8426  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8427  */
8428 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8429 {
8430   std::vector<std::pair<int,int> > edges;
8431   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8432   const int *bgFace=begin;
8433   for(std::size_t i=0;i<nbOfFaces;i++)
8434     {
8435       const int *endFace=std::find(bgFace+1,end,-1);
8436       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8437       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8438         {
8439           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8440           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8441             return false;
8442           edges.push_back(p1);
8443         }
8444       bgFace=endFace+1;
8445     }
8446   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8447 }
8448
8449 /*!
8450  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8451  */
8452 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8453 {
8454   double vec0[3],vec1[3];
8455   std::size_t sz=std::distance(begin,end);
8456   if(sz%2!=0)
8457     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8458   int nbOfNodes=(int)sz/2;
8459   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8460   const double *pt0=coords+3*begin[0];
8461   const double *pt1=coords+3*begin[nbOfNodes];
8462   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8463   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8464 }
8465
8466 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8467 {
8468   std::size_t sz=std::distance(begin,end);
8469   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8470   std::size_t nbOfNodes(sz/2);
8471   std::copy(begin,end,(int *)tmp);
8472   for(std::size_t j=1;j<nbOfNodes;j++)
8473     {
8474       begin[j]=tmp[nbOfNodes-j];
8475       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8476     }
8477 }
8478
8479 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8480 {
8481   std::size_t sz=std::distance(begin,end);
8482   if(sz!=4)
8483     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
8484   double vec0[3],vec1[3];
8485   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8486   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]; 
8487   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;
8488 }
8489
8490 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8491 {
8492   std::size_t sz=std::distance(begin,end);
8493   if(sz!=5)
8494     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
8495   double vec0[3];
8496   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8497   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8498   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8499 }
8500
8501 /*!
8502  * 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 ) 
8503  * 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
8504  * a 2D space.
8505  *
8506  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8507  * \param [in] coords the coordinates with nb of components exactly equal to 3
8508  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8509  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8510  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8511  */
8512 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8513 {
8514   int nbFaces=std::count(begin+1,end,-1)+1;
8515   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8516   double *vPtr=v->getPointer();
8517   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8518   double *pPtr=p->getPointer();
8519   const int *stFaceConn=begin+1;
8520   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8521     {
8522       const int *endFaceConn=std::find(stFaceConn,end,-1);
8523       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8524       stFaceConn=endFaceConn+1;
8525     }
8526   pPtr=p->getPointer(); vPtr=v->getPointer();
8527   DataArrayInt *comm1=0,*commI1=0;
8528   v->findCommonTuples(eps,-1,comm1,commI1);
8529   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8530   const int *comm1Ptr=comm1->getConstPointer();
8531   const int *commI1Ptr=commI1->getConstPointer();
8532   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8533   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8534   //
8535   MCAuto<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8536   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8537   mm->finishInsertingCells();
8538   //
8539   for(int i=0;i<nbOfGrps1;i++)
8540     {
8541       int vecId=comm1Ptr[commI1Ptr[i]];
8542       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8543       DataArrayInt *comm2=0,*commI2=0;
8544       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8545       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8546       const int *comm2Ptr=comm2->getConstPointer();
8547       const int *commI2Ptr=commI2->getConstPointer();
8548       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8549       for(int j=0;j<nbOfGrps2;j++)
8550         {
8551           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8552             {
8553               res->insertAtTheEnd(begin,end);
8554               res->pushBackSilent(-1);
8555             }
8556           else
8557             {
8558               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8559               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
8560               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8561               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8562               MCAuto<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8563               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8564               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8565               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8566               const int *idsNodePtr=idsNode->getConstPointer();
8567               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];
8568               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8569               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8570               if(std::abs(norm)>eps)
8571                 {
8572                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8573                   mm3->rotate(center,vec,angle);
8574                 }
8575               mm3->changeSpaceDimension(2);
8576               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8577               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8578               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8579               int nbOfCells=mm4->getNumberOfCells();
8580               for(int k=0;k<nbOfCells;k++)
8581                 {
8582                   int l=0;
8583                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8584                     res->pushBackSilent(idsNodePtr[*work]);
8585                   res->pushBackSilent(-1);
8586                 }
8587             }
8588         }
8589     }
8590   res->popBackSilent();
8591 }
8592
8593 /*!
8594  * 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
8595  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8596  * 
8597  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8598  * \param [in] coords coordinates expected to have 3 components.
8599  * \param [in] begin start of the nodal connectivity of the face.
8600  * \param [in] end end of the nodal connectivity (excluded) of the face.
8601  * \param [out] v the normalized vector of size 3
8602  * \param [out] p the pos of plane
8603  */
8604 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8605 {
8606   std::size_t nbPoints=std::distance(begin,end);
8607   if(nbPoints<3)
8608     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8609   double vec[3]={0.,0.,0.};
8610   std::size_t j=0;
8611   bool refFound=false;
8612   for(;j<nbPoints-1 && !refFound;j++)
8613     {
8614       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8615       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8616       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8617       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8618       if(norm>eps)
8619         {
8620           refFound=true;
8621           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8622         }
8623     }
8624   for(std::size_t i=j;i<nbPoints-1;i++)
8625     {
8626       double curVec[3];
8627       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8628       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8629       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8630       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8631       if(norm<eps)
8632         continue;
8633       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8634       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];
8635       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8636       if(norm>eps)
8637         {
8638           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8639           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8640           return ;
8641         }
8642     }
8643   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8644 }
8645
8646 /*!
8647  * This method tries to obtain a well oriented polyhedron.
8648  * If the algorithm fails, an exception will be thrown.
8649  */
8650 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8651 {
8652   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8653   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8654   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8655   isPerm[0]=true;
8656   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8657   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8658   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8659   //
8660   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8661     {
8662       bgFace=begin;
8663       std::size_t smthChanged=0;
8664       for(std::size_t i=0;i<nbOfFaces;i++)
8665         {
8666           endFace=std::find(bgFace+1,end,-1);
8667           nbOfEdgesInFace=std::distance(bgFace,endFace);
8668           if(!isPerm[i])
8669             {
8670               bool b;
8671               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8672                 {
8673                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8674                   std::pair<int,int> p2(p1.second,p1.first);
8675                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8676                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8677                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8678                 }
8679               if(isPerm[i])
8680                 { 
8681                   if(!b)
8682                     std::reverse(bgFace+1,endFace);
8683                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8684                     {
8685                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8686                       std::pair<int,int> p2(p1.second,p1.first);
8687                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8688                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
8689                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8690                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
8691                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8692                       if(it!=edgesOK.end())
8693                         {
8694                           edgesOK.erase(it);
8695                           edgesFinished.push_back(p1);
8696                         }
8697                       else
8698                         edgesOK.push_back(p1);
8699                     }
8700                 }
8701             }
8702           bgFace=endFace+1;
8703         }
8704       if(smthChanged==0)
8705         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8706     }
8707   if(!edgesOK.empty())
8708     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8709   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8710     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8711       bgFace=begin;
8712       for(std::size_t i=0;i<nbOfFaces;i++)
8713         {
8714           endFace=std::find(bgFace+1,end,-1);
8715           std::reverse(bgFace+1,endFace);
8716           bgFace=endFace+1;
8717         }
8718     }
8719 }
8720
8721 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8722 {
8723   int nbOfNodesExpected(skin->getNumberOfNodes());
8724   const int *n2oPtr(n2o->getConstPointer());
8725   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8726   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8727   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8728   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8729   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8730   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8731   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8732   if(nbOfNodesExpected<1)
8733     return ret.retn();
8734   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8735   *work++=n2oPtr[prevNode];
8736   for(int i=1;i<nbOfNodesExpected;i++)
8737     {
8738       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8739         {
8740           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8741           conn.erase(prevNode);
8742           if(conn.size()==1)
8743             {
8744               int curNode(*(conn.begin()));
8745               *work++=n2oPtr[curNode];
8746               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8747               shar.erase(prevCell);
8748               if(shar.size()==1)
8749                 {
8750                   prevCell=*(shar.begin());
8751                   prevNode=curNode;
8752                 }
8753               else
8754                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8755             }
8756           else
8757             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8758         }
8759       else
8760         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8761     }
8762   return ret.retn();
8763 }
8764
8765 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8766 {
8767   int nbOfNodesExpected(skin->getNumberOfNodes());
8768   int nbOfTurn(nbOfNodesExpected/2);
8769   const int *n2oPtr(n2o->getConstPointer());
8770   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8771   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8772   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8773   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8774   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8775   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8776   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8777   if(nbOfNodesExpected<1)
8778     return ret.retn();
8779   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8780   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8781   for(int i=1;i<nbOfTurn;i++)
8782     {
8783       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8784         {
8785           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8786           conn.erase(prevNode);
8787           if(conn.size()==1)
8788             {
8789               int curNode(*(conn.begin()));
8790               *work=n2oPtr[curNode];
8791               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8792               shar.erase(prevCell);
8793               if(shar.size()==1)
8794                 {
8795                   int curCell(*(shar.begin()));
8796                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8797                   prevCell=curCell;
8798                   prevNode=curNode;
8799                   work++;
8800                 }
8801               else
8802                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8803             }
8804           else
8805             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8806         }
8807       else
8808         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8809     }
8810   return ret.retn();
8811 }
8812
8813 /*!
8814  * This method makes the assumption spacedimension == meshdimension == 2.
8815  * This method works only for linear cells.
8816  * 
8817  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8818  */
8819 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8820 {
8821   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8822     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8823   MCAuto<MEDCouplingUMesh> skin(computeSkin());
8824   int oldNbOfNodes(skin->getNumberOfNodes());
8825   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
8826   int nbOfNodesExpected(skin->getNumberOfNodes());
8827   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8828   int nbCells(skin->getNumberOfCells());
8829   if(nbCells==nbOfNodesExpected)
8830     return buildUnionOf2DMeshLinear(skin,n2o);
8831   else if(2*nbCells==nbOfNodesExpected)
8832     return buildUnionOf2DMeshQuadratic(skin,n2o);
8833   else
8834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8835 }
8836
8837 /*!
8838  * This method makes the assumption spacedimension == meshdimension == 3.
8839  * This method works only for linear cells.
8840  * 
8841  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8842  */
8843 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8844 {
8845   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8846     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8847   MCAuto<MEDCouplingUMesh> m=computeSkin();
8848   const int *conn=m->getNodalConnectivity()->getConstPointer();
8849   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8850   int nbOfCells=m->getNumberOfCells();
8851   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8852   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8853   if(nbOfCells<1)
8854     return ret.retn();
8855   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8856   for(int i=1;i<nbOfCells;i++)
8857     {
8858       *work++=-1;
8859       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8860     }
8861   return ret.retn();
8862 }
8863
8864 /*!
8865  * \brief Creates a graph of cell neighbors
8866  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8867  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8868  *  For example
8869  *  - index:  0 3 5 6 6
8870  *  - value:  1 2 3 2 3 3
8871  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8872  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8873  */
8874 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8875 {
8876   checkConnectivityFullyDefined();
8877
8878   int meshDim = this->getMeshDimension();
8879   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
8880   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
8881   this->getReverseNodalConnectivity(revConn,indexr);
8882   const int* indexr_ptr=indexr->getConstPointer();
8883   const int* revConn_ptr=revConn->getConstPointer();
8884
8885   const MEDCoupling::DataArrayInt* index;
8886   const MEDCoupling::DataArrayInt* conn;
8887   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8888   index=this->getNodalConnectivityIndex();
8889   int nbCells=this->getNumberOfCells();
8890   const int* index_ptr=index->getConstPointer();
8891   const int* conn_ptr=conn->getConstPointer();
8892
8893   //creating graph arcs (cell to cell relations)
8894   //arcs are stored in terms of (index,value) notation
8895   // 0 3 5 6 6
8896   // 1 2 3 2 3 3
8897   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8898   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8899
8900   //warning here one node have less than or equal effective number of cell with it
8901   //but cell could have more than effective nodes
8902   //because other equals nodes in other domain (with other global inode)
8903   std::vector <int> cell2cell_index(nbCells+1,0);
8904   std::vector <int> cell2cell;
8905   cell2cell.reserve(3*nbCells);
8906
8907   for (int icell=0; icell<nbCells;icell++)
8908     {
8909       std::map<int,int > counter;
8910       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8911         {
8912           int inode=conn_ptr[iconn];
8913           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8914             {
8915               int icell2=revConn_ptr[iconnr];
8916               std::map<int,int>::iterator iter=counter.find(icell2);
8917               if (iter!=counter.end()) (iter->second)++;
8918               else counter.insert(std::make_pair(icell2,1));
8919             }
8920         }
8921       for (std::map<int,int>::const_iterator iter=counter.begin();
8922            iter!=counter.end(); iter++)
8923         if (iter->second >= meshDim)
8924           {
8925             cell2cell_index[icell+1]++;
8926             cell2cell.push_back(iter->first);
8927           }
8928     }
8929   indexr->decrRef();
8930   revConn->decrRef();
8931   cell2cell_index[0]=0;
8932   for (int icell=0; icell<nbCells;icell++)
8933     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8934
8935   //filling up index and value to create skylinearray structure
8936   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8937   return array;
8938 }
8939
8940 /*!
8941  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8942  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8943  */
8944 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8945 {
8946   double *w=zipFrmt;
8947   if(spaceDim==3)
8948     for(int i=0;i<nbOfNodesInCell;i++)
8949       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8950   else if(spaceDim==2)
8951     {
8952       for(int i=0;i<nbOfNodesInCell;i++)
8953         {
8954           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8955           *w++=0.;
8956         }
8957     }
8958   else
8959     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8960 }
8961
8962 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8963 {
8964   int nbOfCells=getNumberOfCells();
8965   if(nbOfCells<=0)
8966     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8967   ofs << "  <" << getVTKDataSetType() << ">\n";
8968   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8969   ofs << "      <PointData>\n" << pointData << std::endl;
8970   ofs << "      </PointData>\n";
8971   ofs << "      <CellData>\n" << cellData << std::endl;
8972   ofs << "      </CellData>\n";
8973   ofs << "      <Points>\n";
8974   if(getSpaceDimension()==3)
8975     _coords->writeVTK(ofs,8,"Points",byteData);
8976   else
8977     {
8978       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8979       coo->writeVTK(ofs,8,"Points",byteData);
8980     }
8981   ofs << "      </Points>\n";
8982   ofs << "      <Cells>\n";
8983   const int *cPtr=_nodal_connec->getConstPointer();
8984   const int *cIPtr=_nodal_connec_index->getConstPointer();
8985   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8986   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8987   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8988   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8989   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8990   int szFaceOffsets=0,szConn=0;
8991   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8992     {
8993       *w2=cPtr[cIPtr[i]];
8994       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8995         {
8996           *w1=-1;
8997           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8998           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8999         }
9000       else
9001         {
9002           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
9003           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
9004           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
9005           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
9006           w4=std::copy(c.begin(),c.end(),w4);
9007         }
9008     }
9009   types->transformWithIndArr(MEDCOUPLING2VTKTYPETRADUCER,MEDCOUPLING2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
9010   types->writeVTK(ofs,8,"UInt8","types",byteData);
9011   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
9012   if(szFaceOffsets!=0)
9013     {//presence of Polyhedra
9014       connectivity->reAlloc(szConn);
9015       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
9016       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
9017       w1=faces->getPointer();
9018       for(int i=0;i<nbOfCells;i++)
9019         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
9020           {
9021             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
9022             *w1++=nbFaces;
9023             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
9024             for(int j=0;j<nbFaces;j++)
9025               {
9026                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
9027                 *w1++=(int)std::distance(w6,w5);
9028                 w1=std::copy(w6,w5,w1);
9029                 w6=w5+1;
9030               }
9031           }
9032       faces->writeVTK(ofs,8,"Int32","faces",byteData);
9033     }
9034   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
9035   ofs << "      </Cells>\n";
9036   ofs << "    </Piece>\n";
9037   ofs << "  </" << getVTKDataSetType() << ">\n";
9038 }
9039
9040 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
9041 {
9042   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
9043   if(_mesh_dim==-2)
9044     { stream << " Not set !"; return ; }
9045   stream << " Mesh dimension : " << _mesh_dim << ".";
9046   if(_mesh_dim==-1)
9047     return ;
9048   if(!_coords)
9049     { stream << " No coordinates set !"; return ; }
9050   if(!_coords->isAllocated())
9051     { stream << " Coordinates set but not allocated !"; return ; }
9052   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
9053   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
9054   if(!_nodal_connec_index)
9055     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
9056   if(!_nodal_connec_index->isAllocated())
9057     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
9058   int lgth=_nodal_connec_index->getNumberOfTuples();
9059   int cpt=_nodal_connec_index->getNumberOfComponents();
9060   if(cpt!=1 || lgth<1)
9061     return ;
9062   stream << std::endl << "Number of cells : " << lgth-1 << ".";
9063 }
9064
9065 std::string MEDCouplingUMesh::getVTKDataSetType() const
9066 {
9067   return std::string("UnstructuredGrid");
9068 }
9069
9070 std::string MEDCouplingUMesh::getVTKFileExtension() const
9071 {
9072   return std::string("vtu");
9073 }
9074
9075 /*!
9076  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
9077  * returns a result mesh constituted by polygons.
9078  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
9079  * all nodes from m2.
9080  * The meshes should be in 2D space. In
9081  * addition, returns two arrays mapping cells of the result mesh to cells of the input
9082  * meshes.
9083  *  \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
9084  *                      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)
9085  *  \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
9086  *                      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)
9087  *  \param [in] eps - precision used to detect coincident mesh entities.
9088  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
9089  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
9090  *         this array using decrRef() as it is no more needed.
9091  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
9092  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
9093  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
9094  *         any cell of \a m2. The caller is to delete this array using decrRef() as
9095  *         it is no more needed.  
9096  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
9097  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
9098  *         is no more needed.  
9099  *  \throw If the coordinates array is not set in any of the meshes.
9100  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
9101  *  \throw If any of the meshes is not a 2D mesh in 2D space.
9102  *
9103  *  \sa conformize2D, mergeNodes
9104  */
9105 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9106                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9107 {
9108   if(!m1 || !m2)
9109     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9110   m1->checkFullyDefined();
9111   m2->checkFullyDefined();
9112   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
9114
9115   // Step 1: compute all edge intersections (new nodes)
9116   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9117   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9118   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9119   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9120   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9121                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9122                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9123   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9124   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9125   MCAuto<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9126
9127   // Step 2: re-order newly created nodes according to the ordering found in m2
9128   std::vector< std::vector<int> > intersectEdge2;
9129   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9130   subDiv2.clear(); dd5=0; dd6=0;
9131
9132   // Step 3:
9133   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9134   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9135   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9136                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9137
9138   // Step 4: Prepare final result:
9139   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
9140   addCooDa->alloc((int)(addCoo.size())/2,2);
9141   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9142   MCAuto<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9143   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9144   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9145   std::vector<const DataArrayDouble *> coordss(4);
9146   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9147   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9148   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9149   MCAuto<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9150   MCAuto<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9151   MCAuto<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9152   MCAuto<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9153   ret->setConnectivity(conn,connI,true);
9154   ret->setCoords(coo);
9155   cellNb1=c1.retn(); cellNb2=c2.retn();
9156   return ret.retn();
9157 }
9158
9159 /// @cond INTERNAL
9160
9161 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9162 {
9163   if(candidates.empty())
9164     return false;
9165   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9166     {
9167       const std::vector<int>& pool(intersectEdge1[*it]);
9168       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9169       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9170         {
9171           retVal=*it+1;
9172           return true;
9173         }
9174       tmp[0]=stop; tmp[1]=start;
9175       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9176         {
9177           retVal=-*it-1;
9178           return true;
9179         }
9180     }
9181   return false;
9182 }
9183
9184 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,
9185                                      MCAuto<DataArrayInt>& idsInRetColinear, MCAuto<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9186 {
9187   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9188   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9189   int nCells(mesh1D->getNumberOfCells());
9190   if(nCells!=(int)intersectEdge2.size())
9191     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9192   const DataArrayDouble *coo2(mesh1D->getCoords());
9193   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9194   const double *coo2Ptr(coo2->begin());
9195   int offset1(coords1->getNumberOfTuples());
9196   int offset2(offset1+coo2->getNumberOfTuples());
9197   int offset3(offset2+addCoo.size()/2);
9198   std::vector<double> addCooQuad;
9199   MCAuto<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9200   int tmp[4],cicnt(0),kk(0);
9201   for(int i=0;i<nCells;i++)
9202     {
9203       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
9204       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9205       const std::vector<int>& subEdges(intersectEdge2[i]);
9206       int nbSubEdge(subEdges.size()/2);
9207       for(int j=0;j<nbSubEdge;j++,kk++)
9208         {
9209           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));
9210           MCAuto<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9211           INTERP_KERNEL::Edge *e2Ptr(e2);
9212           std::map<int,int>::const_iterator itm;
9213           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9214             {
9215               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9216               itm=mergedNodes.find(subEdges[2*j]);
9217               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9218               itm=mergedNodes.find(subEdges[2*j+1]);
9219               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9220               tmp[3]=offset3+(int)addCooQuad.size()/2;
9221               double tmp2[2];
9222               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9223               cicnt+=4;
9224               cOut->insertAtTheEnd(tmp,tmp+4);
9225               ciOut->pushBackSilent(cicnt);
9226             }
9227           else
9228             {
9229               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9230               itm=mergedNodes.find(subEdges[2*j]);
9231               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9232               itm=mergedNodes.find(subEdges[2*j+1]);
9233               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9234               cicnt+=3;
9235               cOut->insertAtTheEnd(tmp,tmp+3);
9236               ciOut->pushBackSilent(cicnt);
9237             }
9238           int tmp00;
9239           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9240             {
9241               idsInRetColinear->pushBackSilent(kk);
9242               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9243             }
9244         }
9245       e->decrRef();
9246     }
9247   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9248   ret->setConnectivity(cOut,ciOut,true);
9249   MCAuto<DataArrayDouble> arr3(DataArrayDouble::New());
9250   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9251   MCAuto<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9252   std::vector<const DataArrayDouble *> coordss(4);
9253   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9254   MCAuto<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9255   ret->setCoords(arr);
9256   return ret.retn();
9257 }
9258
9259 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9260 {
9261   std::vector<int> allEdges;
9262   for(const int *it2(descBg);it2!=descEnd;it2++)
9263     {
9264       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9265       if(*it2>0)
9266         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9267       else
9268         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9269     }
9270   std::size_t nb(allEdges.size());
9271   if(nb%2!=0)
9272     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9273   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9274   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9275   ret->setCoords(coords);
9276   ret->allocateCells(1);
9277   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9278   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9279     connOut[kk]=allEdges[2*kk];
9280   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9281   return ret.retn();
9282 }
9283
9284 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9285 {
9286   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9287   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9288   std::size_t ii(0);
9289   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9290   if(sz!=std::distance(descBg,descEnd))
9291     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9292   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9293   std::vector<int> allEdges,centers;
9294   const double *coordsPtr(coords->begin());
9295   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9296   int offset(coords->getNumberOfTuples());
9297   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9298     {
9299       INTERP_KERNEL::NormalizedCellType typeOfSon;
9300       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9301       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9302       if(*it2>0)
9303         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9304       else
9305         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9306       if(edge1.size()==2)
9307         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9308       else
9309         {//the current edge has been subsplit -> create corresponding centers.
9310           std::size_t nbOfCentersToAppend(edge1.size()/2);
9311           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9312           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9313           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9314           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9315             {
9316               double tmpp[2];
9317               const double *aa(coordsPtr+2*(*it3++));
9318               const double *bb(coordsPtr+2*(*it3++));
9319               ee->getMiddleOfPoints(aa,bb,tmpp);
9320               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9321               centers.push_back(offset+k);
9322             }
9323         }
9324     }
9325   std::size_t nb(allEdges.size());
9326   if(nb%2!=0)
9327     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9328   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9329   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9330   if(addCoo->empty())
9331     ret->setCoords(coords);
9332   else
9333     {
9334       addCoo->rearrange(2);
9335       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9336       ret->setCoords(addCoo);
9337     }
9338   ret->allocateCells(1);
9339   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9340   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9341     connOut[kk]=allEdges[2*kk];
9342   connOut.insert(connOut.end(),centers.begin(),centers.end());
9343   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9344   return ret.retn();
9345 }
9346
9347 /*!
9348  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9349  * of those edges.
9350  *
9351  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9352  */
9353 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9354 {
9355   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9356   if(!cm.isQuadratic())
9357     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9358   else
9359     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9360 }
9361
9362 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edges)
9363 {
9364   bool isQuad(false);
9365   for(std::vector< MCAuto<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9366     {
9367       const INTERP_KERNEL::Edge *ee(*it);
9368       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9369         isQuad=true;
9370     }
9371   if(!isQuad)
9372     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9373   else
9374     {
9375       const double *coo(mesh2D->getCoords()->begin());
9376       std::size_t sz(conn.size());
9377       std::vector<double> addCoo;
9378       std::vector<int> conn2(conn);
9379       int offset(mesh2D->getNumberOfNodes());
9380       for(std::size_t i=0;i<sz;i++)
9381         {
9382           double tmp[2];
9383           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9384           addCoo.insert(addCoo.end(),tmp,tmp+2);
9385           conn2.push_back(offset+(int)i);
9386         }
9387       mesh2D->getCoords()->rearrange(1);
9388       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9389       mesh2D->getCoords()->rearrange(2);
9390       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9391     }
9392 }
9393
9394 /*!
9395  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9396  *
9397  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9398  * a set of edges defined in \a splitMesh1D.
9399  */
9400 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edge1BisPtr,
9401                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& out1)
9402 {
9403   std::size_t nb(edge1Bis.size()/2);
9404   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9405   int iEnd(splitMesh1D->getNumberOfCells());
9406   if(iEnd==0)
9407     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9408   std::size_t ii,jj;
9409   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9410   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9411   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9412   //
9413   if(jj==nb)
9414     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9415       out0.resize(1); out1.resize(1);
9416       std::vector<int>& connOut(out0[0]);
9417       connOut.resize(nbOfEdgesOf2DCellSplit);
9418       std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9419       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9420       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9421         {
9422           connOut[kk]=edge1Bis[2*kk];
9423           edgesPtr[kk]=edge1BisPtr[2*kk];
9424         }
9425     }
9426   else
9427     {
9428       // [i,iEnd[ contains the
9429       out0.resize(2); out1.resize(2);
9430       std::vector<int>& connOutLeft(out0[0]);
9431       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9432       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9433       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eright(out1[1]);
9434       for(std::size_t k=ii;k<jj+1;k++)
9435         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9436       std::vector< MCAuto<INTERP_KERNEL::Edge> > ees(iEnd);
9437       for(int ik=0;ik<iEnd;ik++)
9438         {
9439           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9440           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9441           ees[ik]=ee;
9442         }
9443       for(int ik=iEnd-1;ik>=0;ik--)
9444         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9445       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9446         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9447       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9448       for(int ik=0;ik<iEnd;ik++)
9449         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9450       eright.insert(eright.end(),ees.begin(),ees.end());
9451     }
9452 }
9453
9454 /// @endcond
9455
9456 /// @cond INTERNAL
9457
9458 struct CellInfo
9459 {
9460 public:
9461   CellInfo() { }
9462   CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9463 public:
9464   std::vector<int> _edges;
9465   std::vector< MCAuto<INTERP_KERNEL::Edge> > _edges_ptr;
9466 };
9467
9468 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr)
9469 {
9470   std::size_t nbe(edges.size());
9471   std::vector<int> edges2(2*nbe); std::vector< MCAuto<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9472   for(std::size_t i=0;i<nbe;i++)
9473     {
9474       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9475       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9476     }
9477   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9478   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9479   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9480 }
9481
9482 class EdgeInfo
9483 {
9484 public:
9485   EdgeInfo(int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9486   EdgeInfo(int istart, int iend, int pos, const MCAuto<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9487   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9488   void somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9489   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9490 private:
9491   int _istart;
9492   int _iend;
9493   MCAuto<MEDCouplingUMesh> _mesh;
9494   MCAuto<INTERP_KERNEL::Edge> _edge;
9495   int _left;
9496   int _right;
9497 };
9498
9499 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9500 {
9501   const MEDCouplingUMesh *mesh(_mesh);
9502   if(mesh)
9503     return ;
9504   if(_right<pos)
9505     return ;
9506   if(_left>pos)
9507     { _left++; _right++; return ; }
9508   if(_right==pos)
9509     {
9510       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9511       if((isLeft && isRight) || (!isLeft && !isRight))
9512         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9513       if(isLeft)
9514         return ;
9515       if(isRight)
9516         {
9517           _right++;
9518           return ;
9519         }
9520     }
9521   if(_left==pos)
9522     {
9523       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9524       if((isLeft && isRight) || (!isLeft && !isRight))
9525         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9526       if(isLeft)
9527         {
9528           _right++;
9529           return ;
9530         }
9531       if(isRight)
9532         {
9533           _left++;
9534           _right++;
9535           return ;
9536         }
9537     }
9538 }
9539
9540 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9541 {
9542   const MEDCouplingUMesh *mesh(_mesh);
9543   if(!mesh)
9544     {
9545       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9546     }
9547   else
9548     {// not fully splitting cell case
9549       if(mesh2D->getNumberOfCells()==1)
9550         {//little optimization. 1 cell no need to find in which cell mesh is !
9551           neighbors[0]=offset; neighbors[1]=offset;
9552           return;
9553         }
9554       else
9555         {
9556           MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9557           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9558           if(cellId==-1)
9559             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9560           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9561         }
9562     }
9563 }
9564
9565 class VectorOfCellInfo
9566 {
9567 public:
9568   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9569   std::size_t size() const { return _pool.size(); }
9570   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9571   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);
9572   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9573   const std::vector< MCAuto<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9574   MCAuto<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9575   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9576 private:
9577   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9578   void updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9579   const CellInfo& get(int pos) const;
9580   CellInfo& get(int pos);
9581 private:
9582   std::vector<CellInfo> _pool;
9583   MCAuto<MEDCouplingUMesh> _ze_mesh;
9584   std::vector<EdgeInfo> _edge_info;
9585 };
9586
9587 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9588 {
9589   _pool[0]._edges=edges;
9590   _pool[0]._edges_ptr=edgesPtr;
9591 }
9592
9593 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9594 {
9595   if(_pool.empty())
9596     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9597   if(_pool.size()==1)
9598     return 0;
9599   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9600   if(!zeMesh)
9601     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9602   MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9603   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9604 }
9605
9606 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)
9607 {
9608   get(pos);//to check pos
9609   bool isFast(pos==0 && _pool.size()==1);
9610   std::size_t sz(edges.size());
9611   // dealing with edges
9612   if(sz==1)
9613     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9614   else
9615     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9616   //
9617   std::vector<CellInfo> pool(_pool.size()-1+sz);
9618   for(int i=0;i<pos;i++)
9619     pool[i]=_pool[i];
9620   for(std::size_t j=0;j<sz;j++)
9621     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9622   for(int i=pos+1;i<(int)_pool.size();i++)
9623     pool[i+sz-1]=_pool[i];
9624   _pool=pool;
9625   //
9626   if(sz==2)
9627     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9628   //
9629   if(isFast)
9630     {
9631       _ze_mesh=mesh;
9632       return ;
9633     }
9634   //
9635   std::vector< MCAuto<MEDCouplingUMesh> > ms;
9636   if(pos>0)
9637     {
9638       MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(0,pos,true)));
9639       ms.push_back(elt);
9640     }
9641   ms.push_back(mesh);
9642   if(pos<_ze_mesh->getNumberOfCells()-1)
9643   {
9644     MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(pos+1,_ze_mesh->getNumberOfCells(),true)));
9645     ms.push_back(elt);
9646   }
9647   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9648   for(std::size_t j=0;j<ms2.size();j++)
9649     ms2[j]=ms[j];
9650   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9651 }
9652
9653 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9654 {
9655   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9656 }
9657
9658 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9659 {
9660   if(pos<0)
9661     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9662   int ret(0);
9663   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9664     {
9665       if((*it).isInMyRange(pos))
9666         return ret;
9667     }
9668   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9669 }
9670
9671 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9672 {
9673   get(pos);//to check;
9674   if(_edge_info.empty())
9675     return ;
9676   std::size_t sz(_edge_info.size()-1);
9677   for(std::size_t i=0;i<sz;i++)
9678     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9679 }
9680
9681 const CellInfo& VectorOfCellInfo::get(int pos) const
9682 {
9683   if(pos<0 || pos>=(int)_pool.size())
9684     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9685   return _pool[pos];
9686 }
9687
9688 CellInfo& VectorOfCellInfo::get(int pos)
9689 {
9690   if(pos<0 || pos>=(int)_pool.size())
9691     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9692   return _pool[pos];
9693 }
9694
9695 /*!
9696  * Given :
9697  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9698  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9699  *
9700  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9701  *
9702  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9703  *
9704  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9705  */
9706 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9707                                          MCAuto<DataArrayInt>& idsLeftRight)
9708 {
9709   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9710   if(nbCellsInSplitMesh1D==0)
9711     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9712   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9713   std::size_t nb(allEdges.size()),jj;
9714   if(nb%2!=0)
9715     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9716   std::vector<int> edge1Bis(nb*2);
9717   std::vector< MCAuto<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9718   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9719   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9720   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9721   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9722   //
9723   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9724   int *idsLeftRightPtr(idsLeftRight->getPointer());
9725   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9726   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9727     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9728       int iEnd(iStart);
9729       for(;iEnd<nbCellsInSplitMesh1D;)
9730         {
9731           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9732           if(jj!=nb)
9733             break;
9734           else
9735             iEnd++;
9736         }
9737       if(iEnd<nbCellsInSplitMesh1D)
9738         iEnd++;
9739       //
9740       MCAuto<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelfSlice(iStart,iEnd,1,true)));
9741       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9742       //
9743       MCAuto<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9744       retTmp->setCoords(splitMesh1D->getCoords());
9745       retTmp->allocateCells();
9746
9747       std::vector< std::vector<int> > out0;
9748       std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > > out1;
9749
9750       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9751       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9752         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9753       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9754       //
9755       iStart=iEnd;
9756     }
9757   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9758     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9759   return pool.getZeMesh().retn();
9760 }
9761
9762 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9763                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9764                                      MCAuto<DataArrayInt>& idsLeftRight)
9765 {
9766   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9767   //
9768   std::vector<int> allEdges;
9769   std::vector< MCAuto<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9770   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9771     {
9772       int edgeId(std::abs(*it)-1);
9773       std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9774       MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9775       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9776       if(*it>0)
9777         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9778       else
9779         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9780       std::size_t sz(edge1.size());
9781       for(std::size_t cnt=0;cnt<sz;cnt++)
9782         allEdgesPtr.push_back(ee);
9783     }
9784   //
9785   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9786 }
9787
9788 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9789 {
9790   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9791     {//easy case comparison not
9792       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9793     }
9794   else if(typ1.isQuadratic() && typ2.isQuadratic())
9795     {
9796       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9797       if(!status0)
9798         return false;
9799       if(conn1[2]==conn2[2])
9800         return true;
9801       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9802       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9803       return dist<eps;
9804     }
9805   else
9806     {//only one is quadratic
9807       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9808       if(!status0)
9809         return false;
9810       const double *a(0),*bb(0),*be(0);
9811       if(typ1.isQuadratic())
9812         {
9813           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9814         }
9815       else
9816         {
9817           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9818         }
9819       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9820       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9821       return dist<eps;
9822     }
9823 }
9824
9825 /*!
9826  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9827  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9828  *
9829  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9830  */
9831 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9832 {
9833   if(candidatesIn2DEnd==candidatesIn2DBg)
9834     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9835   const double *coo(mesh2DSplit->getCoords()->begin());
9836   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9837     return *candidatesIn2DBg;
9838   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9839   MCAuto<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9840   if(cellIdInMesh1DSplitRelative<0)
9841     cur1D->changeOrientationOfCells();
9842   const int *c1D(cur1D->getNodalConnectivity()->begin());
9843   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9844   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9845     {
9846       MCAuto<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9847       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9848       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9849       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9850       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9851       for(unsigned it2=0;it2<sz;it2++)
9852         {
9853           INTERP_KERNEL::NormalizedCellType typeOfSon;
9854           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9855           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9856           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9857             return *it;
9858         }
9859     }
9860   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9861 }
9862
9863 /// @endcond
9864
9865 /*!
9866  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9867  * 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
9868  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9869  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9870  *
9871  * \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
9872  *                      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)
9873  * \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
9874  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9875  * \param [in] eps - precision used to perform intersections and localization operations.
9876  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9877  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9878  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9879  *                               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.
9880  * \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
9881  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9882  *                               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.
9883  *
9884  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9885  */
9886 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9887 {
9888   if(!mesh2D || !mesh1D)
9889     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9890   mesh2D->checkFullyDefined();
9891   mesh1D->checkFullyDefined();
9892   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9893   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9894     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9895   // Step 1: compute all edge intersections (new nodes)
9896   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9897   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9898   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9899   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9900   //
9901   // Build desc connectivity
9902   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9903   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9904   MCAuto<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9905   std::map<int,int> mergedNodes;
9906   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9907   // use mergeNodes to fix intersectEdge1
9908   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9909     {
9910       std::size_t n((*it0).size()/2);
9911       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9912       std::map<int,int>::const_iterator it1;
9913       it1=mergedNodes.find(eltStart);
9914       if(it1!=mergedNodes.end())
9915         (*it0)[0]=(*it1).second;
9916       it1=mergedNodes.find(eltEnd);
9917       if(it1!=mergedNodes.end())
9918         (*it0)[2*n-1]=(*it1).second;
9919     }
9920   //
9921   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
9922   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9923   // Step 2: re-order newly created nodes according to the ordering found in m2
9924   std::vector< std::vector<int> > intersectEdge2;
9925   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9926   subDiv2.clear();
9927   // Step 3: compute splitMesh1D
9928   MCAuto<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9929   MCAuto<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9930   MCAuto<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9931       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9932   MCAuto<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9933   MCAuto<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9934   // deal with cells in mesh2D that are not cut but only some of their edges are
9935   MCAuto<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCopy());
9936   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9937   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9938   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
9939   if(!idsInDesc2DToBeRefined->empty())
9940     {
9941       DataArrayInt *out0(0),*outi0(0);
9942       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9943       MCAuto<DataArrayInt> outi0s(outi0);
9944       out0s=out0;
9945       out0s=out0s->buildUnique();
9946       out0s->sort(true);
9947     }
9948   //
9949   MCAuto<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9950   MCAuto<DataArrayDouble> baryRet1(ret1NonCol->computeCellCenterOfMass());
9951   MCAuto<DataArrayInt> elts,eltsIndex;
9952   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9953   MCAuto<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9954   MCAuto<DataArrayInt> eltsIndex3(eltsIndex2->findIdsEqual(1));
9955   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9956     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9957   MCAuto<DataArrayInt> cellsToBeModified(elts->buildUnique());
9958   MCAuto<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9959   if((DataArrayInt *)out0s)
9960     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9961   std::vector< MCAuto<MEDCouplingUMesh> > outMesh2DSplit;
9962   // OK all is ready to insert in ret2 mesh
9963   if(!untouchedCells->empty())
9964     {// the most easy part, cells in mesh2D not impacted at all
9965       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9966       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9967       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9968     }
9969   if((DataArrayInt *)out0s)
9970     {// here dealing with cells in out0s but not in cellsToBeModified
9971       MCAuto<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9972       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9973       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9974         {
9975           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9976           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9977         }
9978       int offset(ret2->getNumberOfTuples());
9979       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9980       MCAuto<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9981       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9982       int kk(0),*ret3ptr(partOfRet3->getPointer());
9983       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9984         {
9985           int faceId(std::abs(*it)-1);
9986           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9987             {
9988               int tmp(fewModifiedCells->findIdFirstEqual(*it2));
9989               if(tmp!=-1)
9990                 {
9991                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9992                     ret3ptr[2*kk]=tmp+offset;
9993                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9994                     ret3ptr[2*kk+1]=tmp+offset;
9995                 }
9996               else
9997                 {//the current edge is shared by a 2D cell that will be split just after
9998                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9999                     ret3ptr[2*kk]=-(*it2+1);
10000                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
10001                     ret3ptr[2*kk+1]=-(*it2+1);
10002                 }
10003             }
10004         }
10005       m1Desc->setCoords(ret1->getCoords());
10006       ret1NonCol->setCoords(ret1->getCoords());
10007       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
10008       if(!outMesh2DSplit.empty())
10009         {
10010           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
10011           for(std::vector< MCAuto<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
10012             (*itt)->setCoords(da);
10013         }
10014     }
10015   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
10016   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
10017     {
10018       MCAuto<DataArrayInt> idsNonColPerCell(elts->findIdsEqual(*it));
10019       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
10020       MCAuto<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
10021       MCAuto<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
10022       MCAuto<DataArrayInt> partOfRet3;
10023       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));
10024       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
10025       outMesh2DSplit.push_back(splitOfOneCell);
10026       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
10027         ret2->pushBackSilent(*it);
10028     }
10029   //
10030   std::size_t nbOfMeshes(outMesh2DSplit.size());
10031   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
10032   for(std::size_t i=0;i<nbOfMeshes;i++)
10033     tmp[i]=outMesh2DSplit[i];
10034   //
10035   ret1->getCoords()->setInfoOnComponents(compNames);
10036   MCAuto<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
10037   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
10038   ret3->rearrange(1);
10039   MCAuto<DataArrayInt> edgesToDealWith(ret3->findIdsStricltyNegative());
10040   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
10041     {
10042       int old2DCellId(-ret3->getIJ(*it,0)-1);
10043       MCAuto<DataArrayInt> candidates(ret2->findIdsEqual(old2DCellId));
10044       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
10045     }
10046   ret3->changeValue(std::numeric_limits<int>::max(),-1);
10047   ret3->rearrange(2);
10048   //
10049   splitMesh1D=ret1.retn();
10050   splitMesh2D=ret2D.retn();
10051   cellIdInMesh2D=ret2.retn();
10052   cellIdInMesh1D=ret3.retn();
10053 }
10054
10055 /**
10056  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
10057  * (newly created) nodes corresponding to the edge intersections.
10058  * Output params:
10059  * @param[out] cr, crI connectivity of the resulting mesh
10060  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
10061  * TODO: describe input parameters
10062  */
10063 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
10064                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
10065                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
10066                                                          const std::vector<double>& addCoords,
10067                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
10068 {
10069   static const int SPACEDIM=2;
10070   const double *coo1(m1->getCoords()->getConstPointer());
10071   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
10072   int offset1(m1->getNumberOfNodes());
10073   const double *coo2(m2->getCoords()->getConstPointer());
10074   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
10075   int offset2(offset1+m2->getNumberOfNodes());
10076   int offset3(offset2+((int)addCoords.size())/2);
10077   MCAuto<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
10078   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10079   // Here a BBTree on 2D-cells, not on segments:
10080   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
10081   int ncell1(m1->getNumberOfCells());
10082   crI.push_back(0);
10083   for(int i=0;i<ncell1;i++)
10084     {
10085       std::vector<int> candidates2;
10086       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10087       std::map<INTERP_KERNEL::Node *,int> mapp;
10088       std::map<int,INTERP_KERNEL::Node *> mappRev;
10089       INTERP_KERNEL::QuadraticPolygon pol1;
10090       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
10091       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
10092       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
10093       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
10094       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
10095       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
10096           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
10097       //
10098       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
10099       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
10100       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
10101       for(it1.first();!it1.finished();it1.next())
10102         edges1.insert(it1.current()->getPtr());
10103       //
10104       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
10105       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10106       int ii=0;
10107       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10108         {
10109           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10110           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10111           // Complete mapping with elements coming from the current cell it2 in mesh2:
10112           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10113           // pol2 is the new QP in the final merged result.
10114           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10115               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10116         }
10117       ii=0;
10118       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10119         {
10120           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10121           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10122           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10123           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10124         }
10125       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10126       // by m2 but that we still want to keep in the final result.
10127       if(!edges1.empty())
10128         {
10129           try
10130           {
10131               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10132           }
10133           catch(INTERP_KERNEL::Exception& e)
10134           {
10135               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();
10136               throw INTERP_KERNEL::Exception(oss.str());
10137           }
10138         }
10139       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10140         (*it).second->decrRef();
10141     }
10142 }
10143
10144 /**
10145  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10146  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10147  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10148  * The caller is to deal with the resulting DataArrayInt.
10149  *  \throw If the coordinate array is not set.
10150  *  \throw If the nodal connectivity of the cells is not defined.
10151  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10152  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10153  *
10154  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10155  */
10156 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10157 {
10158   checkFullyDefined();
10159   if(getMeshDimension()!=1)
10160     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10161
10162   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10163   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10164   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10165   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10166   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10167   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10168   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10169   const int * dsi(_dsi->getConstPointer());
10170   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
10171   m_points=0;
10172   if (dsii->getNumberOfTuples())
10173     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10174
10175   int nc(getNumberOfCells());
10176   MCAuto<DataArrayInt> result(DataArrayInt::New());
10177   result->alloc(nc,1);
10178
10179   // set of edges not used so far
10180   std::set<int> edgeSet;
10181   for (int i=0; i<nc; edgeSet.insert(i), i++);
10182
10183   int startSeg=0;
10184   int newIdx=0;
10185   // while we have points with only one neighbor segments
10186   do
10187     {
10188       std::list<int> linePiece;
10189       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10190       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10191         {
10192           // Fill the list forward (resp. backward) from the start segment:
10193           int activeSeg = startSeg;
10194           int prevPointId = -20;
10195           int ptId;
10196           while (!edgeSet.empty())
10197             {
10198               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10199                 {
10200                   if (direction==0)
10201                     linePiece.push_back(activeSeg);
10202                   else
10203                     linePiece.push_front(activeSeg);
10204                   edgeSet.erase(activeSeg);
10205                 }
10206
10207               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10208               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10209               if (dsi[ptId] == 1) // hitting the end of the line
10210                 break;
10211               prevPointId = ptId;
10212               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10213               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10214             }
10215         }
10216       // Done, save final piece into DA:
10217       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10218       newIdx += linePiece.size();
10219
10220       // identify next valid start segment (one which is not consumed)
10221       if(!edgeSet.empty())
10222         startSeg = *(edgeSet.begin());
10223     }
10224   while (!edgeSet.empty());
10225   return result.retn();
10226 }
10227
10228 /// @cond INTERNAL
10229
10230 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10231 {
10232   MCAuto<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10233   std::map<MCAuto<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10234   if(it==m.end())
10235     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10236   int v((*it).second);
10237   if(v==forbVal0 || v==forbVal1)
10238     return ;
10239   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10240     isect.push_back(v);
10241 }
10242
10243 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10244 {
10245   int sz(c.size());
10246   if(sz<=1)
10247     return false;
10248   bool presenceOfOn(false);
10249   for(int i=0;i<sz;i++)
10250     {
10251       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10252       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10253         continue ;
10254       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10255       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10256     }
10257   return presenceOfOn;
10258 }
10259
10260 /// @endcond
10261
10262 /**
10263  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10264  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10265  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10266  * a minimal creation of new nodes is wanted.
10267  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10268  * nodes if a SEG3 is split without information of middle.
10269  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10270  * avoid to have a non conform mesh.
10271  *
10272  * \return int - the number of new nodes created (in most of cases 0).
10273  * 
10274  * \throw If \a this is not coherent.
10275  * \throw If \a this has not spaceDim equal to 2.
10276  * \throw If \a this has not meshDim equal to 2.
10277  * \throw If some subcells needed to be split are orphan.
10278  * \sa MEDCouplingUMesh::conformize2D
10279  */
10280 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10281 {
10282   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10283     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10284   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10285   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10286     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10287   if(midOpt==0 && midOptI==0)
10288     {
10289       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10290       return 0;
10291     }
10292   else if(midOpt!=0 && midOptI!=0)
10293     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10294   else
10295     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10296 }
10297
10298 /*!
10299  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10300  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10301  * 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
10302  * 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).
10303  * 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.
10304  * 
10305  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10306  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10307  *
10308  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10309  * This method expects that all nodes in \a this are not closer than \a eps.
10310  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10311  * 
10312  * \param [in] eps the relative error to detect merged edges.
10313  * \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
10314  *                           that the user is expected to deal with.
10315  *
10316  * \throw If \a this is not coherent.
10317  * \throw If \a this has not spaceDim equal to 2.
10318  * \throw If \a this has not meshDim equal to 2.
10319  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10320  */
10321 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10322 {
10323   static const int SPACEDIM=2;
10324   checkConsistencyLight();
10325   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10326     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10327   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10328   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10329   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10330   MCAuto<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10331   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10332   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10333   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10334   std::vector<double> addCoo;
10335   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10336   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10337   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10338   for(int i=0;i<nDescCell;i++)
10339     {
10340       std::vector<int> candidates;
10341       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10342       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10343         if(*it>i)
10344           {
10345             std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10346             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10347                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10348             INTERP_KERNEL::MergePoints merge;
10349             INTERP_KERNEL::QuadraticPolygon c1,c2;
10350             e1->intersectWith(e2,merge,c1,c2);
10351             e1->decrRef(); e2->decrRef();
10352             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10353               overlapEdge[i].push_back(*it);
10354             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10355               overlapEdge[*it].push_back(i);
10356           }
10357     }
10358   // splitting done. sort intersect point in intersectEdge.
10359   std::vector< std::vector<int> > middle(nDescCell);
10360   int nbOf2DCellsToBeSplit(0);
10361   bool middleNeedsToBeUsed(false);
10362   std::vector<bool> cells2DToTreat(nDescCell,false);
10363   for(int i=0;i<nDescCell;i++)
10364     {
10365       std::vector<int>& isect(intersectEdge[i]);
10366       int sz((int)isect.size());
10367       if(sz>1)
10368         {
10369           std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10370           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10371           e->sortSubNodesAbs(coords,isect);
10372           e->decrRef();
10373         }
10374       if(sz!=0)
10375         {
10376           int idx0(rdi[i]),idx1(rdi[i+1]);
10377           if(idx1-idx0!=1)
10378             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10379           if(!cells2DToTreat[rd[idx0]])
10380             {
10381               cells2DToTreat[rd[idx0]]=true;
10382               nbOf2DCellsToBeSplit++;
10383             }
10384           // try to reuse at most eventual 'middle' of SEG3
10385           std::vector<int>& mid(middle[i]);
10386           mid.resize(sz+1,-1);
10387           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10388             {
10389               middleNeedsToBeUsed=true;
10390               const std::vector<int>& candidates(overlapEdge[i]);
10391               std::vector<int> trueCandidates;
10392               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10393                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10394                   trueCandidates.push_back(*itc);
10395               int stNode(c[ci[i]+1]),endNode(isect[0]);
10396               for(int j=0;j<sz+1;j++)
10397                 {
10398                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10399                     {
10400                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10401                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10402                         { mid[j]=*itc; break; }
10403                     }
10404                   stNode=endNode;
10405                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10406                 }
10407             }
10408         }
10409     }
10410   MCAuto<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10411   if(nbOf2DCellsToBeSplit==0)
10412     return ret.retn();
10413   //
10414   int *retPtr(ret->getPointer());
10415   for(int i=0;i<nCell;i++)
10416     if(cells2DToTreat[i])
10417       *retPtr++=i;
10418   //
10419   MCAuto<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10420   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10421   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10422   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10423   if(middleNeedsToBeUsed)
10424     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10425   MCAuto<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10426   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10427   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.
10428   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10429   {
10430     bool areNodesMerged; int newNbOfNodes;
10431     if(nbOfNodesCreated!=0)
10432       MCAuto<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10433   }
10434   return ret.retn();
10435 }
10436
10437 /*!
10438  * 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.
10439  * 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).
10440  * 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
10441  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10442  * 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
10443  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10444  *
10445  * 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
10446  * using new instance, idem for coordinates.
10447  *
10448  * 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.
10449  * 
10450  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10451  *
10452  * \throw If \a this is not coherent.
10453  * \throw If \a this has not spaceDim equal to 2.
10454  * \throw If \a this has not meshDim equal to 2.
10455  * 
10456  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10457  */
10458 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10459 {
10460   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10461   checkConsistencyLight();
10462   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10463     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10464   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10465   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10466   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10467   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10468   MCAuto<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10469   MCAuto<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10470   const double *coords(_coords->begin());
10471   int *newciptr(newci->getPointer());
10472   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10473     {
10474       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10475         ret->pushBackSilent(i);
10476       newciptr[1]=newc->getNumberOfTuples();
10477     }
10478   //
10479   if(ret->empty())
10480     return ret.retn();
10481   if(!appendedCoords->empty())
10482     {
10483       appendedCoords->rearrange(2);
10484       MCAuto<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10485       //non const part
10486       setCoords(newCoords);
10487     }
10488   //non const part
10489   setConnectivity(newc,newci,true);
10490   return ret.retn();
10491 }
10492
10493 /*!
10494  * \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.
10495  *                               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.
10496  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10497  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10498  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10499  * \param [out] addCoo - nodes to be append at the end
10500  * \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.
10501  */
10502 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10503                                          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)
10504 {
10505   static const int SPACEDIM=2;
10506   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10507   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10508   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10509   // Build BB tree of all edges in the tool mesh (second mesh)
10510   MCAuto<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10511   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10512   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10513   intersectEdge1.resize(nDescCell1);
10514   colinear2.resize(nDescCell2);
10515   subDiv2.resize(nDescCell2);
10516   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10517
10518   std::vector<int> candidates1(1);
10519   int offset1(m1Desc->getNumberOfNodes());
10520   int offset2(offset1+m2Desc->getNumberOfNodes());
10521   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10522     {
10523       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10524       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10525       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10526         {
10527           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10528           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10529           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10530           candidates1[0]=i;
10531           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10532           // 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
10533           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10534           std::set<INTERP_KERNEL::Node *> nodes;
10535           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10536           std::size_t szz(nodes.size());
10537           std::vector< MCAuto<INTERP_KERNEL::Node> > nodesSafe(szz);
10538           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10539           for(std::size_t iii=0;iii<szz;iii++,itt++)
10540             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10541           // end of protection
10542           // Performs egde cutting:
10543           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10544           delete pol2;
10545           delete pol1;
10546         }
10547       else
10548         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10549         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10550     }
10551 }
10552
10553 /*!
10554  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10555  * It builds the descending connectivity of the two meshes, and then using a binary tree
10556  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10557  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10558  */
10559 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10560                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10561                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10562                                                    std::vector<double>& addCoo,
10563                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10564 {
10565   // Build desc connectivity
10566   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10567   desc2=DataArrayInt::New();
10568   descIndx2=DataArrayInt::New();
10569   revDesc2=DataArrayInt::New();
10570   revDescIndx2=DataArrayInt::New();
10571   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10572   MCAuto<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10573   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10574   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10575   MCAuto<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10576   std::map<int,int> notUsedMap;
10577   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10578   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10579   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10580 }
10581
10582 /*!
10583  * This method performs the 2nd step of Partition of 2D mesh.
10584  * This method has 4 inputs :
10585  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10586  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10587  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10588  * 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'
10589  * Nodes end up lying consecutively on a cutted edge.
10590  * \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.
10591  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10592  * \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.
10593  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10594  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10595  */
10596 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10597                                            const std::vector<double>& addCoo,
10598                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10599 {
10600   int offset1=m1->getNumberOfNodes();
10601   int ncell=m2->getNumberOfCells();
10602   const int *c=m2->getNodalConnectivity()->getConstPointer();
10603   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10604   const double *coo=m2->getCoords()->getConstPointer();
10605   const double *cooBis=m1->getCoords()->getConstPointer();
10606   int offset2=offset1+m2->getNumberOfNodes();
10607   intersectEdge.resize(ncell);
10608   for(int i=0;i<ncell;i++,cI++)
10609     {
10610       const std::vector<int>& divs=subDiv[i];
10611       int nnode=cI[1]-cI[0]-1;
10612       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10613       std::map<INTERP_KERNEL::Node *, int> mapp22;
10614       for(int j=0;j<nnode;j++)
10615         {
10616           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10617           int nnid=c[(*cI)+j+1];
10618           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10619           mapp22[nn]=nnid+offset1;
10620         }
10621       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10622       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10623         ((*it).second.first)->decrRef();
10624       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10625       std::map<INTERP_KERNEL::Node *,int> mapp3;
10626       for(std::size_t j=0;j<divs.size();j++)
10627         {
10628           int id=divs[j];
10629           INTERP_KERNEL::Node *tmp=0;
10630           if(id<offset1)
10631             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10632           else if(id<offset2)
10633             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10634           else
10635             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10636           addNodes[j]=tmp;
10637           mapp3[tmp]=id;
10638         }
10639       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10640       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10641         (*it)->decrRef();
10642       e->decrRef();
10643     }
10644 }
10645
10646 /*!
10647  * 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).
10648  * 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
10649  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10650  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10651  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10652  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10653  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10654  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10655  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10656  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10657  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10658  * \param [out] cut3DSuf input/output param.
10659  */
10660 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10661                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10662                                                    const int *desc, const int *descIndx, 
10663                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10664 {
10665   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10666   int nbOf3DSurfCell=(int)cut3DSurf.size();
10667   for(int i=0;i<nbOf3DSurfCell;i++)
10668     {
10669       std::vector<int> res;
10670       int offset=descIndx[i];
10671       int nbOfSeg=descIndx[i+1]-offset;
10672       for(int j=0;j<nbOfSeg;j++)
10673         {
10674           int edgeId=desc[offset+j];
10675           int status=cut3DCurve[edgeId];
10676           if(status!=-2)
10677             {
10678               if(status>-1)
10679                 res.push_back(status);
10680               else
10681                 {
10682                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10683                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10684                 }
10685             }
10686         }
10687       switch(res.size())
10688       {
10689         case 2:
10690           {
10691             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10692             break;
10693           }
10694         case 1:
10695         case 0:
10696           {
10697             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10698             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10699             if(res.size()==2)
10700               {
10701                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10702               }
10703             else
10704               {
10705                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10706               }
10707             break;
10708           }
10709         default:
10710           {// case when plane is on a multi colinear edge of a polyhedron
10711             if((int)res.size()==2*nbOfSeg)
10712               {
10713                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10714               }
10715             else
10716               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10717           }
10718       }
10719     }
10720 }
10721
10722 /*!
10723  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10724  * 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).
10725  * 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
10726  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10727  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10728  * \param desc is the descending connectivity 3D->3DSurf
10729  * \param descIndx is the descending connectivity index 3D->3DSurf
10730  */
10731 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10732                                                   const int *desc, const int *descIndx,
10733                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10734 {
10735   checkFullyDefined();
10736   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10737     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10738   const int *nodal3D=_nodal_connec->getConstPointer();
10739   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10740   int nbOfCells=getNumberOfCells();
10741   for(int i=0;i<nbOfCells;i++)
10742     {
10743       std::map<int, std::set<int> > m;
10744       int offset=descIndx[i];
10745       int nbOfFaces=descIndx[i+1]-offset;
10746       int start=-1;
10747       int end=-1;
10748       for(int j=0;j<nbOfFaces;j++)
10749         {
10750           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10751           if(p.first!=-1 && p.second!=-1)
10752             {
10753               if(p.first!=-2)
10754                 {
10755                   start=p.first; end=p.second;
10756                   m[p.first].insert(p.second);
10757                   m[p.second].insert(p.first);
10758                 }
10759               else
10760                 {
10761                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10762                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10763                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10764                   INTERP_KERNEL::NormalizedCellType cmsId;
10765                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10766                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10767                   for(unsigned k=0;k<nbOfNodesSon;k++)
10768                     {
10769                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10770                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10771                     }
10772                 }
10773             }
10774         }
10775       if(m.empty())
10776         continue;
10777       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10778       int prev=end;
10779       while(end!=start)
10780         {
10781           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10782           const std::set<int>& s=(*it).second;
10783           std::set<int> s2; s2.insert(prev);
10784           std::set<int> s3;
10785           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10786           if(s3.size()==1)
10787             {
10788               int val=*s3.begin();
10789               conn.push_back(start);
10790               prev=start;
10791               start=val;
10792             }
10793           else
10794             start=end;
10795         }
10796       conn.push_back(end);
10797       if(conn.size()>3)
10798         {
10799           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10800           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10801           cellIds->pushBackSilent(i);
10802         }
10803     }
10804 }
10805
10806 /*!
10807  * 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
10808  * 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
10809  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10810  * 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
10811  * 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.
10812  * 
10813  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10814  */
10815 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10816 {
10817   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10818   if(sz>=4)
10819     {
10820       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10821       if(cm.getDimension()==2)
10822         {
10823           const int *node=nodalConnBg+1;
10824           int startNode=*node++;
10825           double refX=coords[2*startNode];
10826           for(;node!=nodalConnEnd;node++)
10827             {
10828               if(coords[2*(*node)]<refX)
10829                 {
10830                   startNode=*node;
10831                   refX=coords[2*startNode];
10832                 }
10833             }
10834           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10835           refX=1e300;
10836           double tmp1;
10837           double tmp2[2];
10838           double angle0=-M_PI/2;
10839           //
10840           int nextNode=-1;
10841           int prevNode=-1;
10842           double resRef;
10843           double angleNext=0.;
10844           while(nextNode!=startNode)
10845             {
10846               nextNode=-1;
10847               resRef=1e300;
10848               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10849                 {
10850                   if(*node!=tmpOut.back() && *node!=prevNode)
10851                     {
10852                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10853                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10854                       double res;
10855                       if(angleM<=angle0)
10856                         res=angle0-angleM;
10857                       else
10858                         res=angle0-angleM+2.*M_PI;
10859                       if(res<resRef)
10860                         {
10861                           nextNode=*node;
10862                           resRef=res;
10863                           angleNext=angleM;
10864                         }
10865                     }
10866                 }
10867               if(nextNode!=startNode)
10868                 {
10869                   angle0=angleNext-M_PI;
10870                   if(angle0<-M_PI)
10871                     angle0+=2*M_PI;
10872                   prevNode=tmpOut.back();
10873                   tmpOut.push_back(nextNode);
10874                 }
10875             }
10876           std::vector<int> tmp3(2*(sz-1));
10877           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10878           std::copy(nodalConnBg+1,nodalConnEnd,it);
10879           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10880             {
10881               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10882               return false;
10883             }
10884           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10885             {
10886               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10887               return false;
10888             }
10889           else
10890             {
10891               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10892               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10893               return true;
10894             }
10895         }
10896       else
10897         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10898     }
10899   else
10900     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10901 }
10902
10903 /*!
10904  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10905  * 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.
10906  * 
10907  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10908  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10909  * \param [in,out] arr array in which the remove operation will be done.
10910  * \param [in,out] arrIndx array in the remove operation will modify
10911  * \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])
10912  * \return true if \b arr and \b arrIndx have been modified, false if not.
10913  */
10914 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10915 {
10916   if(!arrIndx || !arr)
10917     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10918   if(offsetForRemoval<0)
10919     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10920   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10921   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10922   int *arrIPtr=arrIndx->getPointer();
10923   *arrIPtr++=0;
10924   int previousArrI=0;
10925   const int *arrPtr=arr->getConstPointer();
10926   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10927   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10928     {
10929       if(*arrIPtr-previousArrI>offsetForRemoval)
10930         {
10931           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10932             {
10933               if(s.find(*work)==s.end())
10934                 arrOut.push_back(*work);
10935             }
10936         }
10937       previousArrI=*arrIPtr;
10938       *arrIPtr=(int)arrOut.size();
10939     }
10940   if(arr->getNumberOfTuples()==(int)arrOut.size())
10941     return false;
10942   arr->alloc((int)arrOut.size(),1);
10943   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10944   return true;
10945 }
10946
10947 /*!
10948  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10949  * (\ref numbering-indirect).
10950  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10951  * The selection of extraction is done standardly in new2old format.
10952  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10953  *
10954  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10955  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10956  * \param [in] arrIn arr origin array from which the extraction will be done.
10957  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10958  * \param [out] arrOut the resulting array
10959  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10960  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
10961  */
10962 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10963                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10964 {
10965   if(!arrIn || !arrIndxIn)
10966     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10967   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10968   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10969     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10970   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10971   const int *arrInPtr=arrIn->getConstPointer();
10972   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10973   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10974   if(nbOfGrps<0)
10975     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10976   int maxSizeOfArr=arrIn->getNumberOfTuples();
10977   MCAuto<DataArrayInt> arro=DataArrayInt::New();
10978   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
10979   arrIo->alloc((int)(sz+1),1);
10980   const int *idsIt=idsOfSelectBg;
10981   int *work=arrIo->getPointer();
10982   *work++=0;
10983   int lgth=0;
10984   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10985     {
10986       if(*idsIt>=0 && *idsIt<nbOfGrps)
10987         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10988       else
10989         {
10990           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10991           throw INTERP_KERNEL::Exception(oss.str());
10992         }
10993       if(lgth>=work[-1])
10994         *work=lgth;
10995       else
10996         {
10997           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10998           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10999           throw INTERP_KERNEL::Exception(oss.str());
11000         }
11001     }
11002   arro->alloc(lgth,1);
11003   work=arro->getPointer();
11004   idsIt=idsOfSelectBg;
11005   for(std::size_t i=0;i<sz;i++,idsIt++)
11006     {
11007       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
11008         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
11009       else
11010         {
11011           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
11012           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
11013           throw INTERP_KERNEL::Exception(oss.str());
11014         }
11015     }
11016   arrOut=arro.retn();
11017   arrIndexOut=arrIo.retn();
11018 }
11019
11020 /*!
11021  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
11022  * (\ref numbering-indirect).
11023  * 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 ).
11024  * The selection of extraction is done standardly in new2old format.
11025  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
11026  *
11027  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
11028  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
11029  * \param [in] idsOfSelectStep
11030  * \param [in] arrIn arr origin array from which the extraction will be done.
11031  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11032  * \param [out] arrOut the resulting array
11033  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11034  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
11035  */
11036 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11037                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11038 {
11039   if(!arrIn || !arrIndxIn)
11040     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
11041   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
11042   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
11043     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
11044   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
11045   const int *arrInPtr=arrIn->getConstPointer();
11046   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11047   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
11048   if(nbOfGrps<0)
11049     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
11050   int maxSizeOfArr=arrIn->getNumberOfTuples();
11051   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11052   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11053   arrIo->alloc((int)(sz+1),1);
11054   int idsIt=idsOfSelectStart;
11055   int *work=arrIo->getPointer();
11056   *work++=0;
11057   int lgth=0;
11058   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
11059     {
11060       if(idsIt>=0 && idsIt<nbOfGrps)
11061         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
11062       else
11063         {
11064           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
11065           throw INTERP_KERNEL::Exception(oss.str());
11066         }
11067       if(lgth>=work[-1])
11068         *work=lgth;
11069       else
11070         {
11071           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
11072           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
11073           throw INTERP_KERNEL::Exception(oss.str());
11074         }
11075     }
11076   arro->alloc(lgth,1);
11077   work=arro->getPointer();
11078   idsIt=idsOfSelectStart;
11079   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
11080     {
11081       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
11082         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
11083       else
11084         {
11085           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
11086           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
11087           throw INTERP_KERNEL::Exception(oss.str());
11088         }
11089     }
11090   arrOut=arro.retn();
11091   arrIndexOut=arrIo.retn();
11092 }
11093
11094 /*!
11095  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11096  * 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
11097  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11098  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11099  *
11100  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11101  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11102  * \param [in] arrIn arr origin array from which the extraction will be done.
11103  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11104  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
11105  * \param [in] srcArrIndex index array of \b srcArr
11106  * \param [out] arrOut the resulting array
11107  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11108  * 
11109  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11110  */
11111 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11112                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11113                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11114 {
11115   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11117   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11118   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11119   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11120   std::vector<bool> v(nbOfTuples,true);
11121   int offset=0;
11122   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11123   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11124   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11125     {
11126       if(*it>=0 && *it<nbOfTuples)
11127         {
11128           v[*it]=false;
11129           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11130         }
11131       else
11132         {
11133           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11134           throw INTERP_KERNEL::Exception(oss.str());
11135         }
11136     }
11137   srcArrIndexPtr=srcArrIndex->getConstPointer();
11138   arrIo->alloc(nbOfTuples+1,1);
11139   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11140   const int *arrInPtr=arrIn->getConstPointer();
11141   const int *srcArrPtr=srcArr->getConstPointer();
11142   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11143   int *arroPtr=arro->getPointer();
11144   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11145     {
11146       if(v[ii])
11147         {
11148           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11149           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11150         }
11151       else
11152         {
11153           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11154           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11155           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11156         }
11157     }
11158   arrOut=arro.retn();
11159   arrIndexOut=arrIo.retn();
11160 }
11161
11162 /*!
11163  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11164  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11165  *
11166  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11167  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11168  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11169  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11170  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11171  * \param [in] srcArrIndex index array of \b srcArr
11172  * 
11173  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11174  */
11175 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11176                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11177 {
11178   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11179     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11180   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11181   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11182   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11183   int *arrInOutPtr=arrInOut->getPointer();
11184   const int *srcArrPtr=srcArr->getConstPointer();
11185   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11186     {
11187       if(*it>=0 && *it<nbOfTuples)
11188         {
11189           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11190             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11191           else
11192             {
11193               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] !";
11194               throw INTERP_KERNEL::Exception(oss.str());
11195             }
11196         }
11197       else
11198         {
11199           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11200           throw INTERP_KERNEL::Exception(oss.str());
11201         }
11202     }
11203 }
11204
11205 /*!
11206  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11207  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11208  * 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]].
11209  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11210  * A negative value in \b arrIn means that it is ignored.
11211  * 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.
11212  * 
11213  * \param [in] arrIn arr origin array from which the extraction will be done.
11214  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11215  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11216  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11217  */
11218 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11219 {
11220   int seed=0,nbOfDepthPeelingPerformed=0;
11221   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11222 }
11223
11224 /*!
11225  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11226  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11227  * 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]].
11228  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11229  * A negative value in \b arrIn means that it is ignored.
11230  * 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.
11231  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11232  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11233  * \param [in] arrIn arr origin array from which the extraction will be done.
11234  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11235  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11236  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11237  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11238  * \sa MEDCouplingUMesh::partitionBySpreadZone
11239  */
11240 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11241 {
11242   nbOfDepthPeelingPerformed=0;
11243   if(!arrIndxIn)
11244     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11245   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11246   if(nbOfTuples<=0)
11247     {
11248       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11249       return ret;
11250     }
11251   //
11252   std::vector<bool> fetched(nbOfTuples,false);
11253   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11254 }
11255
11256 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11257 {
11258   nbOfDepthPeelingPerformed=0;
11259   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11260     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11261   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11262   std::vector<bool> fetched2(nbOfTuples,false);
11263   int i=0;
11264   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11265     {
11266       if(*seedElt>=0 && *seedElt<nbOfTuples)
11267         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11268       else
11269         { 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()); }
11270     }
11271   const int *arrInPtr=arrIn->getConstPointer();
11272   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11273   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11274   std::vector<int> idsToFetch1(seedBg,seedEnd);
11275   std::vector<int> idsToFetch2;
11276   std::vector<int> *idsToFetch=&idsToFetch1;
11277   std::vector<int> *idsToFetchOther=&idsToFetch2;
11278   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11279     {
11280       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11281         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11282           if(!fetched[*it2])
11283             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11284       std::swap(idsToFetch,idsToFetchOther);
11285       idsToFetchOther->clear();
11286       nbOfDepthPeelingPerformed++;
11287     }
11288   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11289   i=0;
11290   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11291   int *retPtr=ret->getPointer();
11292   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11293     if(*it)
11294       *retPtr++=i;
11295   return ret.retn();
11296 }
11297
11298 /*!
11299  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11300  * 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
11301  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11302  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11303  *
11304  * \param [in] start begin of set of ids of the input extraction (included)
11305  * \param [in] end end of set of ids of the input extraction (excluded)
11306  * \param [in] step step of the set of ids in range mode.
11307  * \param [in] arrIn arr origin array from which the extraction will be done.
11308  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11309  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11310  * \param [in] srcArrIndex index array of \b srcArr
11311  * \param [out] arrOut the resulting array
11312  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11313  * 
11314  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11315  */
11316 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11317                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11318                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11319 {
11320   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11321     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
11322   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11323   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11324   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11325   int offset=0;
11326   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11327   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11328   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
11329   int it=start;
11330   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11331     {
11332       if(it>=0 && it<nbOfTuples)
11333         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11334       else
11335         {
11336           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11337           throw INTERP_KERNEL::Exception(oss.str());
11338         }
11339     }
11340   srcArrIndexPtr=srcArrIndex->getConstPointer();
11341   arrIo->alloc(nbOfTuples+1,1);
11342   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11343   const int *arrInPtr=arrIn->getConstPointer();
11344   const int *srcArrPtr=srcArr->getConstPointer();
11345   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11346   int *arroPtr=arro->getPointer();
11347   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11348     {
11349       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11350       if(pos<0)
11351         {
11352           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11353           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11354         }
11355       else
11356         {
11357           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11358           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11359         }
11360     }
11361   arrOut=arro.retn();
11362   arrIndexOut=arrIo.retn();
11363 }
11364
11365 /*!
11366  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11367  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11368  *
11369  * \param [in] start begin of set of ids of the input extraction (included)
11370  * \param [in] end end of set of ids of the input extraction (excluded)
11371  * \param [in] step step of the set of ids in range mode.
11372  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11373  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11374  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11375  * \param [in] srcArrIndex index array of \b srcArr
11376  * 
11377  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11378  */
11379 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11380                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11381 {
11382   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11383     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
11384   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11385   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11386   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11387   int *arrInOutPtr=arrInOut->getPointer();
11388   const int *srcArrPtr=srcArr->getConstPointer();
11389   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
11390   int it=start;
11391   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11392     {
11393       if(it>=0 && it<nbOfTuples)
11394         {
11395           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11396             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11397           else
11398             {
11399               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11400               throw INTERP_KERNEL::Exception(oss.str());
11401             }
11402         }
11403       else
11404         {
11405           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11406           throw INTERP_KERNEL::Exception(oss.str());
11407         }
11408     }
11409 }
11410
11411 /*!
11412  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11413  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11414  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11415  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11416  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11417  * 
11418  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11419  */
11420 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11421 {
11422   checkFullyDefined();
11423   int mdim=getMeshDimension();
11424   int spaceDim=getSpaceDimension();
11425   if(mdim!=spaceDim)
11426     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11427   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11428   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11429   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
11430   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11431   ret->setCoords(getCoords());
11432   ret->allocateCells((int)partition.size());
11433   //
11434   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11435     {
11436       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11437       MCAuto<DataArrayInt> cell;
11438       switch(mdim)
11439       {
11440         case 2:
11441           cell=tmp->buildUnionOf2DMesh();
11442           break;
11443         case 3:
11444           cell=tmp->buildUnionOf3DMesh();
11445           break;
11446         default:
11447           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11448       }
11449
11450       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11451     }
11452   //
11453   ret->finishInsertingCells();
11454   return ret.retn();
11455 }
11456
11457 /*!
11458  * This method partitions \b this into contiguous zone.
11459  * This method only needs a well defined connectivity. Coordinates are not considered here.
11460  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11461  */
11462 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11463 {
11464   int nbOfCellsCur=getNumberOfCells();
11465   std::vector<DataArrayInt *> ret;
11466   if(nbOfCellsCur<=0)
11467     return ret;
11468   DataArrayInt *neigh=0,*neighI=0;
11469   computeNeighborsOfCells(neigh,neighI);
11470   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11471   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11472   std::vector< MCAuto<DataArrayInt> > ret2;
11473   int seed=0;
11474   while(seed<nbOfCellsCur)
11475     {
11476       int nbOfPeelPerformed=0;
11477       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11478       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11479     }
11480   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11481     ret.push_back((*it).retn());
11482   return ret;
11483 }
11484
11485 /*!
11486  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11487  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11488  *
11489  * \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.
11490  * \return a newly allocated DataArrayInt to be managed by the caller.
11491  * \throw In case of \a code has not the right format (typically of size 3*n)
11492  */
11493 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11494 {
11495   MCAuto<DataArrayInt> ret=DataArrayInt::New();
11496   std::size_t nb=code.size()/3;
11497   if(code.size()%3!=0)
11498     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11499   ret->alloc((int)nb,2);
11500   int *retPtr=ret->getPointer();
11501   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11502     {
11503       retPtr[0]=code[3*i+2];
11504       retPtr[1]=code[3*i+2]+code[3*i+1];
11505     }
11506   return ret.retn();
11507 }
11508
11509 /*!
11510  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11511  * All cells in \a this are expected to be linear 3D cells.
11512  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11513  * It leads to an increase to number of cells.
11514  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11515  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11516  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11517  *
11518  * \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.
11519  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11520  * \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. 
11521  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11522  *          an id of old cell producing it. The caller is to delete this array using
11523  *         decrRef() as it is no more needed.
11524  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11525  *
11526  * \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
11527  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11528  * 
11529  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11530  * \throw If \a this is not fully constituted with linear 3D cells.
11531  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11532  */
11533 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11534 {
11535   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11536   checkConnectivityFullyDefined();
11537   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11538     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11539   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11540   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11541   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11542   int *retPt(ret->getPointer());
11543   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11544   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11545   const int *oldc(_nodal_connec->begin());
11546   const int *oldci(_nodal_connec_index->begin());
11547   const double *coords(_coords->begin());
11548   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11549     {
11550       std::vector<int> a; std::vector<double> b;
11551       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11552       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11553       const int *aa(&a[0]);
11554       if(!b.empty())
11555         {
11556           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11557             if(*it<0)
11558               *it=(-(*(it))-1+nbNodes);
11559           addPts->insertAtTheEnd(b.begin(),b.end());
11560           nbNodes+=(int)b.size()/3;
11561         }
11562       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11563         newConn->insertAtTheEnd(aa,aa+4);
11564     }
11565   if(!addPts->empty())
11566     {
11567       addPts->rearrange(3);
11568       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11569       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11570       ret0->setCoords(addPts);
11571     }
11572   else
11573     {
11574       nbOfAdditionalPoints=0;
11575       ret0->setCoords(getCoords());
11576     }
11577   ret0->setNodalConnectivity(newConn);
11578   //
11579   ret->computeOffsetsFull();
11580   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11581   return ret0.retn();
11582 }
11583
11584 /*!
11585  * 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). 
11586  *
11587  * \sa MEDCouplingUMesh::split2DCells
11588  */
11589 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11590 {
11591   checkConnectivityFullyDefined();
11592   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+subNodesInSeg->getNumberOfTuples());
11593   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11594   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11595   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11596   int prevPosOfCi(ciPtr[0]);
11597   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11598     {
11599       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11600       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11601       for(int j=0;j<sz;j++)
11602         {
11603           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11604           for(int k=0;k<sz2;k++)
11605             *cPtr++=subPtr[offset2+k];
11606           if(j!=sz-1)
11607             *cPtr++=oldConn[prevPosOfCi+j+2];
11608           deltaSz+=sz2;
11609         }
11610       prevPosOfCi=ciPtr[1];
11611       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11612     }
11613   if(c->end()!=cPtr)
11614     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11615   _nodal_connec->decrRef();
11616   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11617 }
11618
11619 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11620 {
11621   if(id!=-1)
11622     return id;
11623   else
11624     {
11625       int ret(nodesCnter++);
11626       double newPt[2];
11627       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11628       addCoo.insertAtTheEnd(newPt,newPt+2);
11629       return ret;
11630     }
11631 }
11632
11633 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11634 {
11635   if(id!=-1)
11636     return id;
11637   else
11638     {
11639       int ret(nodesCnter++);
11640       double newPt[2];
11641       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11642       addCoo.insertAtTheEnd(newPt,newPt+2);
11643       return ret;
11644     }
11645 }
11646
11647
11648 /// @cond INTERNAL
11649
11650 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)
11651 {
11652   int tmp[3];
11653   int trueStart(start>=0?start:nbOfEdges+start);
11654   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11655   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11656   if(linOrArc)
11657     {
11658       if(stp-start>1)
11659         {
11660           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11661           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11662           middles.push_back(tmp3+offset);
11663         }
11664       else
11665         middles.push_back(connBg[trueStart+nbOfEdges]);
11666     }
11667 }
11668
11669 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)
11670 {
11671   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11672   newConnOfCell->pushBackSilent(tmpEnd);
11673   if(linOrArc)
11674     {
11675       if(stp-start>1)
11676         {
11677           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11678           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11679           middles.push_back(tmp3+offset);
11680         }
11681       else
11682         middles.push_back(connBg[start+nbOfEdges]);
11683     }
11684 }
11685
11686 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)
11687 {
11688   // only the quadratic point to deal with:
11689   if(linOrArc)
11690     {
11691       if(stp-start>1)
11692         {
11693           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11694           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11695           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11696           middles.push_back(tmp3+offset);
11697         }
11698       else
11699         middles.push_back(connBg[start+nbOfEdges]);
11700     }
11701 }
11702
11703 /// @endcond
11704
11705 /*!
11706  * 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 ) .
11707  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11708  */
11709 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11710 {
11711   std::size_t sz(std::distance(connBg,connEnd));
11712   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11713     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11714   sz--;
11715   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11716   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11717   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11718   unsigned nbOfHit(0); // number of fusions operated
11719   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11720   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
11721   INTERP_KERNEL::NormalizedCellType typeOfSon;
11722   std::vector<int> middles;
11723   bool ret(false);
11724   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11725     {
11726       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11727       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
11728       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11729       posEndElt = posBaseElt+1;
11730
11731       // Look backward first: are the final edges of the cells colinear with the first ones?
11732       // This initializes posBaseElt.
11733       if(nbOfTurn==0)
11734         {
11735           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11736             {
11737               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11738               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11739               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11740               bool isColinear=eint->areColinears();
11741               if(isColinear)
11742                 {
11743                   nbOfHit++;
11744                   posBaseElt--;
11745                   ret=true;
11746                 }
11747               delete eint;
11748               eCand->decrRef();
11749               if(!isColinear)
11750                 break;
11751             }
11752         }
11753       // Now move forward:
11754       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11755       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11756         {
11757           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11758           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11759           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11760           bool isColinear(eint->areColinears());
11761           if(isColinear)
11762             {
11763               nbOfHit++;
11764               posEndElt++;
11765               ret=true;
11766             }
11767           delete eint;
11768           eCand->decrRef();
11769           if(!isColinear)
11770               break;
11771         }
11772       //push [posBaseElt,posEndElt) in newConnOfCell using e
11773       // 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!
11774       if(nbOfTurn==0)
11775         // at the begining of the connectivity (insert type)
11776         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11777       else if((nbOfHit+nbOfTurn) != (nbs-1))
11778         // in the middle
11779         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11780       if ((nbOfHit+nbOfTurn) == (nbs-1))
11781         // at the end (only quad points to deal with)
11782         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11783       posBaseElt=posEndElt;
11784       e->decrRef();
11785     }
11786   if(!middles.empty())
11787     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11788   return ret;
11789 }
11790
11791 /*!
11792  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11793  *
11794  * \return  int - the number of new nodes created.
11795  * \sa MEDCouplingUMesh::split2DCells
11796  */
11797 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11798 {
11799   checkConsistencyLight();
11800   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11801   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11802   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11803   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11804   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11805   const double *oldCoordsPtr(getCoords()->begin());
11806   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11807   int prevPosOfCi(ciPtr[0]);
11808   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11809     {
11810       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11811       for(int j=0;j<sz;j++)
11812         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11813       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11814       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11815         {
11816           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11817           if(sz2==0)
11818             {
11819               if(j<sz-1)
11820                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11821               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11822               continue;
11823             }
11824           std::vector<INTERP_KERNEL::Node *> ns(3);
11825           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11826           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11827           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11828           MCAuto<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11829           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11830             {
11831               cPtr[1]=subPtr[offset2+k];
11832               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11833             }
11834           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11835           if(j!=sz-1)
11836             { cPtr[1]=tmpEnd; }
11837           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11838         }
11839       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11840       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11841     }
11842   if(c->end()!=cPtr)
11843     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11844   _nodal_connec->decrRef();
11845   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11846   addCoo->rearrange(2);
11847   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11848   setCoords(coo);
11849   return addCoo->getNumberOfTuples();
11850 }
11851
11852 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11853 {
11854   if(nodalConnec && nodalConnecIndex)
11855     {
11856       types.clear();
11857       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11858       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11859       if(nbOfElem>0)
11860         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11861           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11862     }
11863 }
11864
11865 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11866     _own_cell(true),_cell_id(-1),_nb_cell(0)
11867 {
11868   if(mesh)
11869     {
11870       mesh->incrRef();
11871       _nb_cell=mesh->getNumberOfCells();
11872     }
11873 }
11874
11875 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11876 {
11877   if(_mesh)
11878     _mesh->decrRef();
11879   if(_own_cell)
11880     delete _cell;
11881 }
11882
11883 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11884     _own_cell(false),_cell_id(bg-1),
11885     _nb_cell(end)
11886 {
11887   if(mesh)
11888     mesh->incrRef();
11889 }
11890
11891 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11892 {
11893   _cell_id++;
11894   if(_cell_id<_nb_cell)
11895     {
11896       _cell->next();
11897       return _cell;
11898     }
11899   else
11900     return 0;
11901 }
11902
11903 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11904 {
11905   if(_mesh)
11906     _mesh->incrRef();
11907 }
11908
11909 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11910 {
11911   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11912 }
11913
11914 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11915 {
11916   if(_mesh)
11917     _mesh->decrRef();
11918 }
11919
11920 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11921     _itc(itc),
11922     _bg(bg),_end(end)
11923 {
11924   if(_mesh)
11925     _mesh->incrRef();
11926 }
11927
11928 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11929 {
11930   if(_mesh)
11931     _mesh->decrRef();
11932 }
11933
11934 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11935 {
11936   return _type;
11937 }
11938
11939 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11940 {
11941   return _end-_bg;
11942 }
11943
11944 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11945 {
11946   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11947 }
11948
11949 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11950 {
11951   if(mesh)
11952     {
11953       mesh->incrRef();
11954       _nb_cell=mesh->getNumberOfCells();
11955     }
11956 }
11957
11958 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11959 {
11960   if(_mesh)
11961     _mesh->decrRef();
11962   delete _cell;
11963 }
11964
11965 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11966 {
11967   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11968   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11969   if(_cell_id<_nb_cell)
11970     {
11971       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11972       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
11973       int startId=_cell_id;
11974       _cell_id+=nbOfElems;
11975       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11976     }
11977   else
11978     return 0;
11979 }
11980
11981 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11982 {
11983   if(mesh)
11984     {
11985       _conn=mesh->getNodalConnectivity()->getPointer();
11986       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11987     }
11988 }
11989
11990 void MEDCouplingUMeshCell::next()
11991 {
11992   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11993     {
11994       _conn+=_conn_lgth;
11995       _conn_indx++;
11996     }
11997   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11998 }
11999
12000 std::string MEDCouplingUMeshCell::repr() const
12001 {
12002   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
12003     {
12004       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
12005       oss << " : ";
12006       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
12007       return oss.str();
12008     }
12009   else
12010     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
12011 }
12012
12013 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
12014 {
12015   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
12016     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
12017   else
12018     return INTERP_KERNEL::NORM_ERROR;
12019 }
12020
12021 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
12022 {
12023   lgth=_conn_lgth;
12024   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
12025     return _conn;
12026   else
12027     return 0;
12028 }