Salome HOME
Make the medcoupling to VTK accessible from the outside. For MEDWriter.
[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().c_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().c_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().c_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().c_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().c_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().c_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().c_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().c_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 /// @endcond
678
679 /*!
680  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
681  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
682  * describing correspondence between cells of \a this and the result meshes are
683  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
684  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
685  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
686  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
687  * \warning For speed reasons, this method does not check if node ids in the nodal
688  *          connectivity correspond to the size of node coordinates array.
689  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
690  *          to write this mesh to the MED file, its cells must be sorted using
691  *          sortCellsInMEDFileFrmt().
692  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
693  *         each cell of \a this mesh.
694  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
695  *        dividing cell ids in \a desc into groups each referring to one
696  *        cell of \a this mesh. Its every element (except the last one) is an index
697  *        pointing to the first id of a group of cells. For example cells of the
698  *        result mesh bounding the cell #1 of \a this mesh are described by following
699  *        range of indices:
700  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
701  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
702  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
703  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
704  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
705  *         by each cell of the result mesh.
706  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
707  *        in the result mesh,
708  *        dividing cell ids in \a revDesc into groups each referring to one
709  *        cell of the result mesh the same way as \a descIndx divides \a desc.
710  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
711  *        delete this mesh using decrRef() as it is no more needed.
712  *  \throw If the coordinates array is not set.
713  *  \throw If the nodal connectivity of cells is node defined.
714  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
715  *         revDescIndx == NULL.
716  * 
717  *  \if ENABLE_EXAMPLES
718  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
719  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
720  *  \endif
721  * \sa buildDescendingConnectivity2()
722  */
723 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
724 {
725   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
726 }
727
728 /*!
729  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
730  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
731  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
732  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
733  * \sa MEDCouplingUMesh::buildDescendingConnectivity
734  */
735 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
736 {
737   checkFullyDefined();
738   if(getMeshDimension()!=3)
739     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
740   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
741 }
742
743 /*!
744  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
745  * this->getMeshDimension(), that bound cells of \a this mesh. In
746  * addition arrays describing correspondence between cells of \a this and the result
747  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
748  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
749  *  mesh. This method differs from buildDescendingConnectivity() in that apart
750  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
751  * result meshes. So a positive id means that order of nodes in corresponding cells
752  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
753  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
754  * i.e. cell ids are one-based.
755  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
756  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
757  * \warning For speed reasons, this method does not check if node ids in the nodal
758  *          connectivity correspond to the size of node coordinates array.
759  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
760  *          to write this mesh to the MED file, its cells must be sorted using
761  *          sortCellsInMEDFileFrmt().
762  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
763  *         each cell of \a this mesh.
764  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
765  *        dividing cell ids in \a desc into groups each referring to one
766  *        cell of \a this mesh. Its every element (except the last one) is an index
767  *        pointing to the first id of a group of cells. For example cells of the
768  *        result mesh bounding the cell #1 of \a this mesh are described by following
769  *        range of indices:
770  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
771  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
772  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
773  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
774  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
775  *         by each cell of the result mesh.
776  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
777  *        in the result mesh,
778  *        dividing cell ids in \a revDesc into groups each referring to one
779  *        cell of the result mesh the same way as \a descIndx divides \a desc.
780  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
781  *        shares the node coordinates array with \a this mesh. The caller is to
782  *        delete this mesh using decrRef() as it is no more needed.
783  *  \throw If the coordinates array is not set.
784  *  \throw If the nodal connectivity of cells is node defined.
785  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
786  *         revDescIndx == NULL.
787  * 
788  *  \if ENABLE_EXAMPLES
789  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
790  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
791  *  \endif
792  * \sa buildDescendingConnectivity()
793  */
794 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
795 {
796   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
797 }
798
799 /*!
800  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
801  * For speed reasons no check of this will be done. This method calls
802  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
803  * This method lists cell by cell in \b this which are its neighbors. To compute the result
804  * only connectivities are considered.
805  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
806  * The format of return is hence \ref numbering-indirect.
807  *
808  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
809  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
810  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
811  * is equal to the last values in \b neighborsIndx.
812  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
813  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
814  */
815 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
816 {
817   MCAuto<DataArrayInt> desc=DataArrayInt::New();
818   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
819   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
820   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
821   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
822   meshDM1=0;
823   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
824 }
825
826 /*!
827  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
828  * of MEDCouplingUMesh::computeNeighborsOfCells.
829  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
830  * typically the case to extract a set a neighbours,
831  * excluding a set of meshdim-1 cells in input descending connectivity.
832  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
833  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
834  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
835  * are considered.
836  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
837  *
838  * \param [in] desc descending connectivity array.
839  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
840  * \param [in] revDesc reverse descending connectivity array.
841  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
842  * \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
843  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
844  * \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.
845  */
846 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
847                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
848 {
849   if(!desc || !descIndx || !revDesc || !revDescIndx)
850     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
851   const int *descPtr=desc->getConstPointer();
852   const int *descIPtr=descIndx->getConstPointer();
853   const int *revDescPtr=revDesc->getConstPointer();
854   const int *revDescIPtr=revDescIndx->getConstPointer();
855   //
856   int nbCells=descIndx->getNumberOfTuples()-1;
857   MCAuto<DataArrayInt> out0=DataArrayInt::New();
858   MCAuto<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
859   int *out1Ptr=out1->getPointer();
860   *out1Ptr++=0;
861   out0->reserve(desc->getNumberOfTuples());
862   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
863     {
864       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
865         {
866           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
867           s.erase(i);
868           out0->insertAtTheEnd(s.begin(),s.end());
869         }
870       *out1Ptr=out0->getNumberOfTuples();
871     }
872   neighbors=out0.retn();
873   neighborsIndx=out1.retn();
874 }
875
876 /*!
877  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
878  * For speed reasons no check of this will be done. This method calls
879  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
880  * This method lists node by node in \b this which are its neighbors. To compute the result
881  * only connectivities are considered.
882  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
883  *
884  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
885  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
886  * parameter allows to select the right part in this array (\ref numbering-indirect).
887  * The number of tuples is equal to the last values in \b neighborsIndx.
888  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
889  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
890  */
891 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
892 {
893   checkFullyDefined();
894   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
895   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
896   MCAuto<MEDCouplingUMesh> mesh1D;
897   switch(mdim)
898   {
899     case 3:
900       {
901         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
902         break;
903       }
904     case 2:
905       {
906         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
907         break;
908       }
909     case 1:
910       {
911         mesh1D=const_cast<MEDCouplingUMesh *>(this);
912         mesh1D->incrRef();
913         break;
914       }
915     default:
916       {
917         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
918       }
919   }
920   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
921   mesh1D->getReverseNodalConnectivity(desc,descIndx);
922   MCAuto<DataArrayInt> ret0(DataArrayInt::New());
923   ret0->alloc(desc->getNumberOfTuples(),1);
924   int *r0Pt(ret0->getPointer());
925   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
926   for(int i=0;i<nbNodes;i++,rni++)
927     {
928       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
929         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
930     }
931   neighbors=ret0.retn();
932   neighborsIdx=descIndx.retn();
933 }
934
935 /// @cond INTERNAL
936
937 /*!
938  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
939  * For speed reasons no check of this will be done.
940  */
941 template<class SonsGenerator>
942 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
943 {
944   if(!desc || !descIndx || !revDesc || !revDescIndx)
945     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
946   checkConnectivityFullyDefined();
947   int nbOfCells=getNumberOfCells();
948   int nbOfNodes=getNumberOfNodes();
949   MCAuto<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
950   int *revNodalIndxPtr=revNodalIndx->getPointer();
951   const int *conn=_nodal_connec->getConstPointer();
952   const int *connIndex=_nodal_connec_index->getConstPointer();
953   std::string name="Mesh constituent of "; name+=getName();
954   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
955   ret->setCoords(getCoords());
956   ret->allocateCells(2*nbOfCells);
957   descIndx->alloc(nbOfCells+1,1);
958   MCAuto<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
959   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
960   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
961     {
962       int pos=connIndex[eltId];
963       int posP1=connIndex[eltId+1];
964       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
965       SonsGenerator sg(cm);
966       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
967       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
968       for(unsigned i=0;i<nbOfSons;i++)
969         {
970           INTERP_KERNEL::NormalizedCellType cmsId;
971           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
972           for(unsigned k=0;k<nbOfNodesSon;k++)
973             if(tmp[k]>=0)
974               revNodalIndxPtr[tmp[k]+1]++;
975           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
976           revDesc2->pushBackSilent(eltId);
977         }
978       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
979     }
980   int nbOfCellsM1=ret->getNumberOfCells();
981   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
982   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
983   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
984   int *revNodalPtr=revNodal->getPointer();
985   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
986   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
987   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
988     {
989       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
990       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
991       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
992         if(*iter>=0)//for polyhedrons
993           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
994     }
995   //
996   DataArrayInt *commonCells=0,*commonCellsI=0;
997   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
998   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
999   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1000   int newNbOfCellsM1=-1;
1001   MCAuto<DataArrayInt> o2nM1=DataArrayInt::ConvertIndexArrayToO2N(nbOfCellsM1,commonCells->begin(),
1002                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1003   std::vector<bool> isImpacted(nbOfCellsM1,false);
1004   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1005     for(int work2=work[0];work2!=work[1];work2++)
1006       isImpacted[commonCellsPtr[work2]]=true;
1007   const int *o2nM1Ptr=o2nM1->getConstPointer();
1008   MCAuto<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1009   const int *n2oM1Ptr=n2oM1->getConstPointer();
1010   MCAuto<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1011   ret2->copyTinyInfoFrom(this);
1012   desc->alloc(descIndx->back(),1);
1013   int *descPtr=desc->getPointer();
1014   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1015   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1016     {
1017       if(!isImpacted[i])
1018         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1019       else
1020         {
1021           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1022             {
1023               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1024               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1025             }
1026           else
1027             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1028         }
1029     }
1030   revDesc->reserve(newNbOfCellsM1);
1031   revDescIndx->alloc(newNbOfCellsM1+1,1);
1032   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1033   const int *revDesc2Ptr=revDesc2->getConstPointer();
1034   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1035     {
1036       int oldCellIdM1=n2oM1Ptr[i];
1037       if(!isImpacted[oldCellIdM1])
1038         {
1039           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1040           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1041         }
1042       else
1043         {
1044           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1045             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1046           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1047           commonCellsIPtr++;
1048         }
1049     }
1050   //
1051   return ret2.retn();
1052 }
1053
1054 struct MEDCouplingAccVisit
1055 {
1056   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1057   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1058   int _new_nb_of_nodes;
1059 };
1060
1061 /// @endcond
1062
1063 /*!
1064  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1065  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1066  * array of cell ids. Pay attention that after conversion all algorithms work slower
1067  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1068  * conversion due presence of invalid ids in the array of cells to convert, as a
1069  * result \a this mesh contains some already converted elements. In this case the 2D
1070  * mesh remains valid but 3D mesh becomes \b inconsistent!
1071  *  \warning This method can significantly modify the order of geometric types in \a this,
1072  *          hence, to write this mesh to the MED file, its cells must be sorted using
1073  *          sortCellsInMEDFileFrmt().
1074  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1075  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1076  *         cellIdsToConvertBg.
1077  *  \throw If the coordinates array is not set.
1078  *  \throw If the nodal connectivity of cells is node defined.
1079  *  \throw If dimension of \a this mesh is not either 2 or 3.
1080  *
1081  *  \if ENABLE_EXAMPLES
1082  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1083  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1084  *  \endif
1085  */
1086 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1087 {
1088   checkFullyDefined();
1089   int dim=getMeshDimension();
1090   if(dim<2 || dim>3)
1091     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1092   int nbOfCells(getNumberOfCells());
1093   if(dim==2)
1094     {
1095       const int *connIndex=_nodal_connec_index->getConstPointer();
1096       int *conn=_nodal_connec->getPointer();
1097       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1098         {
1099           if(*iter>=0 && *iter<nbOfCells)
1100             {
1101               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1102               if(!cm.isQuadratic())
1103                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1104               else
1105                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1106             }
1107           else
1108             {
1109               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1110               oss << " in range [0," << nbOfCells << ") !";
1111               throw INTERP_KERNEL::Exception(oss.str().c_str());
1112             }
1113         }
1114     }
1115   else
1116     {
1117       int *connIndex(_nodal_connec_index->getPointer());
1118       const int *connOld(_nodal_connec->getConstPointer());
1119       MCAuto<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1120       std::vector<bool> toBeDone(nbOfCells,false);
1121       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1122         {
1123           if(*iter>=0 && *iter<nbOfCells)
1124             toBeDone[*iter]=true;
1125           else
1126             {
1127               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1128               oss << " in range [0," << nbOfCells << ") !";
1129               throw INTERP_KERNEL::Exception(oss.str().c_str());
1130             }
1131         }
1132       for(int cellId=0;cellId<nbOfCells;cellId++)
1133         {
1134           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1135           int lgthOld(posP1-pos-1);
1136           if(toBeDone[cellId])
1137             {
1138               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1139               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1140               int *tmp(new int[nbOfFaces*lgthOld+1]);
1141               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1142               for(unsigned j=0;j<nbOfFaces;j++)
1143                 {
1144                   INTERP_KERNEL::NormalizedCellType type;
1145                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1146                   work+=offset;
1147                   *work++=-1;
1148                 }
1149               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1150               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1151               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1152               delete [] tmp;
1153             }
1154           else
1155             {
1156               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1157               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1158             }
1159         }
1160       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1161     }
1162   computeTypes();
1163 }
1164
1165 /*!
1166  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1167  * polyhedrons (if \a this is a 3D mesh).
1168  *  \warning As this method is purely for user-friendliness and no optimization is
1169  *          done to avoid construction of a useless vector, this method can be costly
1170  *          in memory.
1171  *  \throw If the coordinates array is not set.
1172  *  \throw If the nodal connectivity of cells is node defined.
1173  *  \throw If dimension of \a this mesh is not either 2 or 3.
1174  */
1175 void MEDCouplingUMesh::convertAllToPoly()
1176 {
1177   int nbOfCells=getNumberOfCells();
1178   std::vector<int> cellIds(nbOfCells);
1179   for(int i=0;i<nbOfCells;i++)
1180     cellIds[i]=i;
1181   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1182 }
1183
1184 /*!
1185  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1186  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1187  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1188  * base facet of the volume and the second half of nodes describes an opposite facet
1189  * having the same number of nodes as the base one. This method converts such
1190  * connectivity to a valid polyhedral format where connectivity of each facet is
1191  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1192  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1193  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1194  * a correct orientation of the first facet of a polyhedron, else orientation of a
1195  * corrected cell is reverse.<br>
1196  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1197  * it releases the user from boring description of polyhedra connectivity in the valid
1198  * format.
1199  *  \throw If \a this->getMeshDimension() != 3.
1200  *  \throw If \a this->getSpaceDimension() != 3.
1201  *  \throw If the nodal connectivity of cells is not defined.
1202  *  \throw If the coordinates array is not set.
1203  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1204  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1205  *
1206  *  \if ENABLE_EXAMPLES
1207  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1208  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1209  *  \endif
1210  */
1211 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1212 {
1213   checkFullyDefined();
1214   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1215     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1216   int nbOfCells=getNumberOfCells();
1217   MCAuto<DataArrayInt> newCi=DataArrayInt::New();
1218   newCi->alloc(nbOfCells+1,1);
1219   int *newci=newCi->getPointer();
1220   const int *ci=_nodal_connec_index->getConstPointer();
1221   const int *c=_nodal_connec->getConstPointer();
1222   newci[0]=0;
1223   for(int i=0;i<nbOfCells;i++)
1224     {
1225       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1226       if(type==INTERP_KERNEL::NORM_POLYHED)
1227         {
1228           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1229             {
1230               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1231               throw INTERP_KERNEL::Exception(oss.str().c_str());
1232             }
1233           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1234           if(n2%2!=0)
1235             {
1236               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 !";
1237               throw INTERP_KERNEL::Exception(oss.str().c_str());
1238             }
1239           int n1=(int)(n2/2);
1240           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)
1241         }
1242       else
1243         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1244     }
1245   MCAuto<DataArrayInt> newC=DataArrayInt::New();
1246   newC->alloc(newci[nbOfCells],1);
1247   int *newc=newC->getPointer();
1248   for(int i=0;i<nbOfCells;i++)
1249     {
1250       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1251       if(type==INTERP_KERNEL::NORM_POLYHED)
1252         {
1253           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1254           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1255           *newc++=-1;
1256           for(std::size_t j=0;j<n1;j++)
1257             {
1258               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1259               newc[n1+5*j]=-1;
1260               newc[n1+5*j+1]=c[ci[i]+1+j];
1261               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1262               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1263               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1264             }
1265           newc+=n1*6;
1266         }
1267       else
1268         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1269     }
1270   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1271   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1272 }
1273
1274
1275 /*!
1276  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1277  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1278  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1279  *          to write this mesh to the MED file, its cells must be sorted using
1280  *          sortCellsInMEDFileFrmt().
1281  * \warning Cells (and most notably polyhedrons) must be correctly oriented for this to work
1282  *          properly. See orientCorrectlyPolyhedrons() and arePolyhedronsNotCorrectlyOriented().
1283  * \return \c true if at least one cell has been converted, \c false else. In the
1284  *         last case the nodal connectivity remains unchanged.
1285  * \throw If the coordinates array is not set.
1286  * \throw If the nodal connectivity of cells is not defined.
1287  * \throw If \a this->getMeshDimension() < 0.
1288  */
1289 bool MEDCouplingUMesh::unPolyze()
1290 {
1291   checkFullyDefined();
1292   int mdim=getMeshDimension();
1293   if(mdim<0)
1294     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1295   if(mdim<=1)
1296     return false;
1297   int nbOfCells=getNumberOfCells();
1298   if(nbOfCells<1)
1299     return false;
1300   int initMeshLgth=getNodalConnectivityArrayLen();
1301   int *conn=_nodal_connec->getPointer();
1302   int *index=_nodal_connec_index->getPointer();
1303   int posOfCurCell=0;
1304   int newPos=0;
1305   int lgthOfCurCell;
1306   bool ret=false;
1307   for(int i=0;i<nbOfCells;i++)
1308     {
1309       lgthOfCurCell=index[i+1]-posOfCurCell;
1310       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1311       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1312       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1313       int newLgth;
1314       if(cm.isDynamic())
1315         {
1316           switch(cm.getDimension())
1317           {
1318             case 2:
1319               {
1320                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1321                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1322                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1323                 break;
1324               }
1325             case 3:
1326               {
1327                 int nbOfFaces,lgthOfPolyhConn;
1328                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1329                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1330                 break;
1331               }
1332             case 1:
1333               {
1334                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1335                 break;
1336               }
1337           }
1338           ret=ret || (newType!=type);
1339           conn[newPos]=newType;
1340           newPos+=newLgth+1;
1341           posOfCurCell=index[i+1];
1342           index[i+1]=newPos;
1343         }
1344       else
1345         {
1346           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1347           newPos+=lgthOfCurCell;
1348           posOfCurCell+=lgthOfCurCell;
1349           index[i+1]=newPos;
1350         }
1351     }
1352   if(newPos!=initMeshLgth)
1353     _nodal_connec->reAlloc(newPos);
1354   if(ret)
1355     computeTypes();
1356   return ret;
1357 }
1358
1359 /*!
1360  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1361  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1362  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1363  *
1364  * \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 
1365  *             precision.
1366  */
1367 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1368 {
1369   checkFullyDefined();
1370   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1371     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1372   MCAuto<DataArrayDouble> coords=getCoords()->deepCopy();
1373   coords->recenterForMaxPrecision(eps);
1374   //
1375   int nbOfCells=getNumberOfCells();
1376   const int *conn=_nodal_connec->getConstPointer();
1377   const int *index=_nodal_connec_index->getConstPointer();
1378   MCAuto<DataArrayInt> connINew=DataArrayInt::New();
1379   connINew->alloc(nbOfCells+1,1);
1380   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1381   MCAuto<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1382   bool changed=false;
1383   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1384     {
1385       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1386         {
1387           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1388           changed=true;
1389         }
1390       else
1391         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1392       *connINewPtr=connNew->getNumberOfTuples();
1393     }
1394   if(changed)
1395     setConnectivity(connNew,connINew,false);
1396 }
1397
1398 /*!
1399  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1400  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1401  * the format of the returned DataArrayInt instance.
1402  * 
1403  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1404  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1405  */
1406 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1407 {
1408   checkConnectivityFullyDefined();
1409   int nbOfCells=getNumberOfCells();
1410   const int *connIndex=_nodal_connec_index->getConstPointer();
1411   const int *conn=_nodal_connec->getConstPointer();
1412   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1413   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1414   std::vector<bool> retS(maxElt,false);
1415   for(int i=0;i<nbOfCells;i++)
1416     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1417       if(conn[j]>=0)
1418         retS[conn[j]]=true;
1419   int sz=0;
1420   for(int i=0;i<maxElt;i++)
1421     if(retS[i])
1422       sz++;
1423   DataArrayInt *ret=DataArrayInt::New();
1424   ret->alloc(sz,1);
1425   int *retPtr=ret->getPointer();
1426   for(int i=0;i<maxElt;i++)
1427     if(retS[i])
1428       *retPtr++=i;
1429   return ret;
1430 }
1431
1432 /*!
1433  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1434  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1435  */
1436 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1437 {
1438   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1439   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1440   for(int i=0;i<nbOfCells;i++)
1441     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1442       if(conn[j]>=0)
1443         {
1444           if(conn[j]<nbOfNodes)
1445             nodeIdsInUse[conn[j]]=true;
1446           else
1447             {
1448               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1449               throw INTERP_KERNEL::Exception(oss.str().c_str());
1450             }
1451         }
1452 }
1453
1454 /*!
1455  * Finds nodes not used in any cell and returns an array giving a new id to every node
1456  * by excluding the unused nodes, for which the array holds -1. The result array is
1457  * a mapping in "Old to New" mode. 
1458  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1459  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1460  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1461  *          if the node is unused or a new id else. The caller is to delete this
1462  *          array using decrRef() as it is no more needed.  
1463  *  \throw If the coordinates array is not set.
1464  *  \throw If the nodal connectivity of cells is not defined.
1465  *  \throw If the nodal connectivity includes an invalid id.
1466  *
1467  *  \if ENABLE_EXAMPLES
1468  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1469  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1470  *  \endif
1471  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1472  */
1473 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1474 {
1475   nbrOfNodesInUse=-1;
1476   int nbOfNodes(getNumberOfNodes());
1477   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1478   ret->alloc(nbOfNodes,1);
1479   int *traducer=ret->getPointer();
1480   std::fill(traducer,traducer+nbOfNodes,-1);
1481   int nbOfCells=getNumberOfCells();
1482   const int *connIndex=_nodal_connec_index->getConstPointer();
1483   const int *conn=_nodal_connec->getConstPointer();
1484   for(int i=0;i<nbOfCells;i++)
1485     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1486       if(conn[j]>=0)
1487         {
1488           if(conn[j]<nbOfNodes)
1489             traducer[conn[j]]=1;
1490           else
1491             {
1492               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1493               throw INTERP_KERNEL::Exception(oss.str().c_str());
1494             }
1495         }
1496   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1497   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1498   return ret.retn();
1499 }
1500
1501 /*!
1502  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1503  * For each cell in \b this the number of nodes constituting cell is computed.
1504  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1505  * So for pohyhedrons some nodes can be counted several times in the returned result.
1506  * 
1507  * \return a newly allocated array
1508  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1509  */
1510 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1511 {
1512   checkConnectivityFullyDefined();
1513   int nbOfCells=getNumberOfCells();
1514   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1515   ret->alloc(nbOfCells,1);
1516   int *retPtr=ret->getPointer();
1517   const int *conn=getNodalConnectivity()->getConstPointer();
1518   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1519   for(int i=0;i<nbOfCells;i++,retPtr++)
1520     {
1521       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1522         *retPtr=connI[i+1]-connI[i]-1;
1523       else
1524         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1525     }
1526   return ret.retn();
1527 }
1528
1529 /*!
1530  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1531  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1532  *
1533  * \return DataArrayInt * - new object to be deallocated by the caller.
1534  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1535  */
1536 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() 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       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1548       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1549         *retPtr=(int)s.size();
1550       else
1551         {
1552           s.erase(-1);
1553           *retPtr=(int)s.size();
1554         }
1555     }
1556   return ret.retn();
1557 }
1558
1559 /*!
1560  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1561  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1562  * 
1563  * \return a newly allocated array
1564  */
1565 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1566 {
1567   checkConnectivityFullyDefined();
1568   int nbOfCells=getNumberOfCells();
1569   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1570   ret->alloc(nbOfCells,1);
1571   int *retPtr=ret->getPointer();
1572   const int *conn=getNodalConnectivity()->getConstPointer();
1573   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1574   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1575     {
1576       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1577       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1578     }
1579   return ret.retn();
1580 }
1581
1582 /*!
1583  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1584  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1585  * array mean that the corresponding old node is no more used. 
1586  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1587  *           this->getNumberOfNodes() before call of this method. The caller is to
1588  *           delete this array using decrRef() as it is no more needed. 
1589  *  \throw If the coordinates array is not set.
1590  *  \throw If the nodal connectivity of cells is not defined.
1591  *  \throw If the nodal connectivity includes an invalid id.
1592  *  \sa areAllNodesFetched
1593  *
1594  *  \if ENABLE_EXAMPLES
1595  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1596  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1597  *  \endif
1598  */
1599 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1600 {
1601   return MEDCouplingPointSet::zipCoordsTraducer();
1602 }
1603
1604 /*!
1605  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1606  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1607  */
1608 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1609 {
1610   switch(compType)
1611   {
1612     case 0:
1613       return AreCellsEqualPolicy0(conn,connI,cell1,cell2);
1614     case 1:
1615       return AreCellsEqualPolicy1(conn,connI,cell1,cell2);
1616     case 2:
1617       return AreCellsEqualPolicy2(conn,connI,cell1,cell2);
1618     case 3:
1619       return AreCellsEqualPolicy2NoType(conn,connI,cell1,cell2);
1620     case 7:
1621       return AreCellsEqualPolicy7(conn,connI,cell1,cell2);
1622   }
1623   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1624 }
1625
1626 /*!
1627  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1628  */
1629 int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, int cell1, int cell2)
1630 {
1631   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1632     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1633   return 0;
1634 }
1635
1636 /*!
1637  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1638  */
1639 int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, int cell1, int cell2)
1640 {
1641   int sz=connI[cell1+1]-connI[cell1];
1642   if(sz==connI[cell2+1]-connI[cell2])
1643     {
1644       if(conn[connI[cell1]]==conn[connI[cell2]])
1645         {
1646           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1647           unsigned dim=cm.getDimension();
1648           if(dim!=3)
1649             {
1650               if(dim!=1)
1651                 {
1652                   int sz1=2*(sz-1);
1653                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1654                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1655                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1656                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1657                   return work!=tmp+sz1?1:0;
1658                 }
1659               else
1660                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1661             }
1662           else
1663             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy1 : not implemented yet for meshdim == 3 !");
1664         }
1665     }
1666   return 0;
1667 }
1668
1669 /*!
1670  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1671  */
1672 int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, int cell1, int cell2)
1673 {
1674   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1675     {
1676       if(conn[connI[cell1]]==conn[connI[cell2]])
1677         {
1678           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1679           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1680           return s1==s2?1:0;
1681         }
1682     }
1683   return 0;
1684 }
1685
1686 /*!
1687  * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account !
1688  */
1689 int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *connI, int cell1, int cell2)
1690 {
1691   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1692     {
1693       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1694       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1695       return s1==s2?1:0;
1696     }
1697   return 0;
1698 }
1699
1700 /*!
1701  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1702  */
1703 int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, int cell1, int cell2)
1704 {
1705   int sz=connI[cell1+1]-connI[cell1];
1706   if(sz==connI[cell2+1]-connI[cell2])
1707     {
1708       if(conn[connI[cell1]]==conn[connI[cell2]])
1709         {
1710           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1711           unsigned dim=cm.getDimension();
1712           if(dim!=3)
1713             {
1714               if(dim!=1)
1715                 {
1716                   int sz1=2*(sz-1);
1717                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1718                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1719                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1720                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1721                   if(work!=tmp+sz1)
1722                     return 1;
1723                   else
1724                     {
1725                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1726                       std::reverse_iterator<int *> it2((int *)tmp);
1727                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1728                         return 2;
1729                       else
1730                         return 0;
1731                     }
1732
1733                   return work!=tmp+sz1?1:0;
1734                 }
1735               else
1736                 {//case of SEG2 and SEG3
1737                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1738                     return 1;
1739                   if(!cm.isQuadratic())
1740                     {
1741                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1742                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1743                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1744                         return 2;
1745                       return 0;
1746                     }
1747                   else
1748                     {
1749                       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])
1750                         return 2;
1751                       return 0;
1752                     }
1753                 }
1754             }
1755           else
1756             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy7 : not implemented yet for meshdim == 3 !");
1757         }
1758     }
1759   return 0;
1760 }
1761
1762 /*!
1763  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1764  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1765  * and result remains unchanged.
1766  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1767  * If in 'candidates' pool -1 value is considered as an empty value.
1768  * WARNING this method returns only ONE set of result !
1769  */
1770 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1771 {
1772   if(candidates.size()<1)
1773     return false;
1774   bool ret=false;
1775   std::vector<int>::const_iterator iter=candidates.begin();
1776   int start=(*iter++);
1777   for(;iter!=candidates.end();iter++)
1778     {
1779       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1780       if(status!=0)
1781         {
1782           if(!ret)
1783             {
1784               result->pushBackSilent(start);
1785               ret=true;
1786             }
1787           if(status==1)
1788             result->pushBackSilent(*iter);
1789           else
1790             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1791         }
1792     }
1793   return ret;
1794 }
1795
1796 /*!
1797  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1798  * by \a compType.
1799  * This method keeps the coordiantes of \a this. This method is time consuming.
1800  *
1801  * \param [in] compType input specifying the technique used to compare cells each other.
1802  *   - 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.
1803  *   - 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)
1804  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1805  *   - 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
1806  * can be used for users not sensitive to orientation of cell
1807  * \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.
1808  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1809  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1810  * \return the correspondance array old to new in a newly allocated array.
1811  * 
1812  */
1813 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1814 {
1815   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1816   getReverseNodalConnectivity(revNodal,revNodalI);
1817   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1818 }
1819
1820 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1821                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1822 {
1823   MCAuto<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1824   int nbOfCells=nodalI->getNumberOfTuples()-1;
1825   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1826   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1827   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1828   std::vector<bool> isFetched(nbOfCells,false);
1829   if(startCellId==0)
1830     {
1831       for(int i=0;i<nbOfCells;i++)
1832         {
1833           if(!isFetched[i])
1834             {
1835               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1836               std::vector<int> v,v2;
1837               if(connOfNode!=connPtr+connIPtr[i+1])
1838                 {
1839                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1840                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1841                   connOfNode++;
1842                 }
1843               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1844                 if(*connOfNode>=0)
1845                   {
1846                     v=v2;
1847                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1848                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1849                     v2.resize(std::distance(v2.begin(),it));
1850                   }
1851               if(v2.size()>1)
1852                 {
1853                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1854                     {
1855                       int pos=commonCellsI->back();
1856                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1857                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1858                         isFetched[*it]=true;
1859                     }
1860                 }
1861             }
1862         }
1863     }
1864   else
1865     {
1866       for(int i=startCellId;i<nbOfCells;i++)
1867         {
1868           if(!isFetched[i])
1869             {
1870               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1871               std::vector<int> v,v2;
1872               if(connOfNode!=connPtr+connIPtr[i+1])
1873                 {
1874                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1875                   connOfNode++;
1876                 }
1877               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1878                 if(*connOfNode>=0)
1879                   {
1880                     v=v2;
1881                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1882                     v2.resize(std::distance(v2.begin(),it));
1883                   }
1884               if(v2.size()>1)
1885                 {
1886                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1887                     {
1888                       int pos=commonCellsI->back();
1889                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1890                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1891                         isFetched[*it]=true;
1892                     }
1893                 }
1894             }
1895         }
1896     }
1897   commonCellsArr=commonCells.retn();
1898   commonCellsIArr=commonCellsI.retn();
1899 }
1900
1901 /*!
1902  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1903  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1904  * than \a this->getNumberOfCells() in the returned array means that there is no
1905  * corresponding cell in \a this mesh.
1906  * It is expected that \a this and \a other meshes share the same node coordinates
1907  * array, if it is not so an exception is thrown. 
1908  *  \param [in] other - the mesh to compare with.
1909  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1910  *         valid values [0,1,2], see zipConnectivityTraducer().
1911  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1912  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1913  *         values. The caller is to delete this array using
1914  *         decrRef() as it is no more needed.
1915  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1916  *         mesh.
1917  *
1918  *  \if ENABLE_EXAMPLES
1919  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1920  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1921  *  \endif
1922  *  \sa checkDeepEquivalOnSameNodesWith()
1923  *  \sa checkGeoEquivalWith()
1924  */
1925 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1926 {
1927   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1928   int nbOfCells=getNumberOfCells();
1929   static const int possibleCompType[]={0,1,2};
1930   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1931     {
1932       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1933       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1934       oss << " !";
1935       throw INTERP_KERNEL::Exception(oss.str().c_str());
1936     }
1937   MCAuto<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1938   arr=o2n->subArray(nbOfCells);
1939   arr->setName(other->getName());
1940   int tmp;
1941   if(other->getNumberOfCells()==0)
1942     return true;
1943   return arr->getMaxValue(tmp)<nbOfCells;
1944 }
1945
1946 /*!
1947  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1948  * This method tries to determine if \b other is fully included in \b this.
1949  * The main difference is that this method is not expected to throw exception.
1950  * This method has two outputs :
1951  *
1952  * \param other other mesh
1953  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1954  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1955  */
1956 bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1957 {
1958   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1959   DataArrayInt *commonCells=0,*commonCellsI=0;
1960   int thisNbCells=getNumberOfCells();
1961   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1962   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1963   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1964   int otherNbCells=other->getNumberOfCells();
1965   MCAuto<DataArrayInt> arr2=DataArrayInt::New();
1966   arr2->alloc(otherNbCells,1);
1967   arr2->fillWithZero();
1968   int *arr2Ptr=arr2->getPointer();
1969   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1970   for(int i=0;i<nbOfCommon;i++)
1971     {
1972       int start=commonCellsPtr[commonCellsIPtr[i]];
1973       if(start<thisNbCells)
1974         {
1975           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1976             {
1977               int sig=commonCellsPtr[j]>0?1:-1;
1978               int val=std::abs(commonCellsPtr[j])-1;
1979               if(val>=thisNbCells)
1980                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1981             }
1982         }
1983     }
1984   arr2->setName(other->getName());
1985   if(arr2->presenceOfValue(0))
1986     return false;
1987   arr=arr2.retn();
1988   return true;
1989 }
1990
1991 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1992 {
1993   if(!other)
1994     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1995   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1996   if(!otherC)
1997     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1998   std::vector<const MEDCouplingUMesh *> ms(2);
1999   ms[0]=this;
2000   ms[1]=otherC;
2001   return MergeUMeshesOnSameCoords(ms);
2002 }
2003
2004 /*!
2005  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2006  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2007  * cellIds is not given explicitely but by a range python like.
2008  * 
2009  * \param start
2010  * \param end
2011  * \param step
2012  * \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.
2013  * \return a newly allocated
2014  * 
2015  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2016  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2017  */
2018 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, int step, bool keepCoords) const
2019 {
2020   if(getMeshDimension()!=-1)
2021     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords));
2022   else
2023     {
2024       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh ");
2025       if(newNbOfCells!=1)
2026         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2027       if(start!=0)
2028         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2029       incrRef();
2030       return const_cast<MEDCouplingUMesh *>(this);
2031     }
2032 }
2033
2034 /*!
2035  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2036  * The result mesh shares or not the node coordinates array with \a this mesh depending
2037  * on \a keepCoords parameter.
2038  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2039  *           to write this mesh to the MED file, its cells must be sorted using
2040  *           sortCellsInMEDFileFrmt().
2041  *  \param [in] begin - an array of cell ids to include to the new mesh.
2042  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2043  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2044  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2045  *         by calling zipCoords().
2046  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2047  *         to delete this mesh using decrRef() as it is no more needed. 
2048  *  \throw If the coordinates array is not set.
2049  *  \throw If the nodal connectivity of cells is not defined.
2050  *  \throw If any cell id in the array \a begin is not valid.
2051  *
2052  *  \if ENABLE_EXAMPLES
2053  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2054  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2055  *  \endif
2056  */
2057 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2058 {
2059   if(getMeshDimension()!=-1)
2060     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
2061   else
2062     {
2063       if(end-begin!=1)
2064         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2065       if(begin[0]!=0)
2066         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2067       incrRef();
2068       return const_cast<MEDCouplingUMesh *>(this);
2069     }
2070 }
2071
2072 /*!
2073  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2074  *
2075  * 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.
2076  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2077  * The number of cells of \b this will remain the same with this method.
2078  *
2079  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2080  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2081  * \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 ).
2082  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2083  */
2084 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2085 {
2086   checkConnectivityFullyDefined();
2087   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2088   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2089     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2090   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2091     {
2092       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2093       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2094       throw INTERP_KERNEL::Exception(oss.str().c_str());
2095     }
2096   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2097   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2098     {
2099       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2100       throw INTERP_KERNEL::Exception(oss.str().c_str());
2101     }
2102   int nbOfCells=getNumberOfCells();
2103   bool easyAssign=true;
2104   const int *connI=_nodal_connec_index->getConstPointer();
2105   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2106   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2107     {
2108       if(*it>=0 && *it<nbOfCells)
2109         {
2110           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2111         }
2112       else
2113         {
2114           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2115           throw INTERP_KERNEL::Exception(oss.str().c_str());
2116         }
2117     }
2118   if(easyAssign)
2119     {
2120       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2121       computeTypes();
2122     }
2123   else
2124     {
2125       DataArrayInt *arrOut=0,*arrIOut=0;
2126       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2127                                                arrOut,arrIOut);
2128       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2129       setConnectivity(arrOut,arrIOut,true);
2130     }
2131 }
2132
2133 void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2134 {
2135   checkConnectivityFullyDefined();
2136   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2137   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2138     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelfSlice : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2139   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2140     {
2141       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2142       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2143       throw INTERP_KERNEL::Exception(oss.str().c_str());
2144     }
2145   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : ");
2146   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2147     {
2148       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2149       throw INTERP_KERNEL::Exception(oss.str().c_str());
2150     }
2151   int nbOfCells=getNumberOfCells();
2152   bool easyAssign=true;
2153   const int *connI=_nodal_connec_index->getConstPointer();
2154   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2155   int it=start;
2156   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2157     {
2158       if(it>=0 && it<nbOfCells)
2159         {
2160           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2161         }
2162       else
2163         {
2164           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2165           throw INTERP_KERNEL::Exception(oss.str().c_str());
2166         }
2167     }
2168   if(easyAssign)
2169     {
2170       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2171       computeTypes();
2172     }
2173   else
2174     {
2175       DataArrayInt *arrOut=0,*arrIOut=0;
2176       MEDCouplingUMesh::SetPartOfIndexedArraysSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2177                                                 arrOut,arrIOut);
2178       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2179       setConnectivity(arrOut,arrIOut,true);
2180     }
2181 }                      
2182
2183 /*!
2184  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2185  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2186  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2187  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2188  *
2189  * \param [in] begin input start of array of node ids.
2190  * \param [in] end input end of array of node ids.
2191  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2192  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2193  */
2194 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2195 {
2196   MCAuto<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2197   checkConnectivityFullyDefined();
2198   int tmp=-1;
2199   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2200   std::vector<bool> fastFinder(sz,false);
2201   for(const int *work=begin;work!=end;work++)
2202     if(*work>=0 && *work<sz)
2203       fastFinder[*work]=true;
2204   int nbOfCells=getNumberOfCells();
2205   const int *conn=getNodalConnectivity()->getConstPointer();
2206   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2207   for(int i=0;i<nbOfCells;i++)
2208     {
2209       int ref=0,nbOfHit=0;
2210       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2211         if(*work2>=0)
2212           {
2213             ref++;
2214             if(fastFinder[*work2])
2215               nbOfHit++;
2216           }
2217       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2218         cellIdsKept->pushBackSilent(i);
2219     }
2220   cellIdsKeptArr=cellIdsKept.retn();
2221 }
2222
2223 /*!
2224  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2225  * this->getMeshDimension(), that bound some cells of \a this mesh.
2226  * The cells of lower dimension to include to the result mesh are selected basing on
2227  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2228  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2229  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2230  * created mesh shares the node coordinates array with \a this mesh. 
2231  *  \param [in] begin - the array of node ids.
2232  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2233  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2234  *         array \a begin are added, else cells whose any node is in the
2235  *         array \a begin are added.
2236  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2237  *         to delete this mesh using decrRef() as it is no more needed. 
2238  *  \throw If the coordinates array is not set.
2239  *  \throw If the nodal connectivity of cells is not defined.
2240  *  \throw If any node id in \a begin is not valid.
2241  *
2242  *  \if ENABLE_EXAMPLES
2243  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2244  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2245  *  \endif
2246  */
2247 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2248 {
2249   MCAuto<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2250   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2251   MCAuto<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2252   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2253   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2254 }
2255
2256 /*!
2257  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2258  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2259  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2260  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2261  *         by calling zipCoords().
2262  *  \return MEDCouplingUMesh * - a 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  *
2267  *  \if ENABLE_EXAMPLES
2268  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2269  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2270  *  \endif
2271  */
2272 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2273 {
2274   DataArrayInt *desc=DataArrayInt::New();
2275   DataArrayInt *descIndx=DataArrayInt::New();
2276   DataArrayInt *revDesc=DataArrayInt::New();
2277   DataArrayInt *revDescIndx=DataArrayInt::New();
2278   //
2279   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2280   revDesc->decrRef();
2281   desc->decrRef();
2282   descIndx->decrRef();
2283   int nbOfCells=meshDM1->getNumberOfCells();
2284   const int *revDescIndxC=revDescIndx->getConstPointer();
2285   std::vector<int> boundaryCells;
2286   for(int i=0;i<nbOfCells;i++)
2287     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2288       boundaryCells.push_back(i);
2289   revDescIndx->decrRef();
2290   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2291   return ret;
2292 }
2293
2294 /*!
2295  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2296  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2297  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2298  */
2299 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2300 {
2301   checkFullyDefined();
2302   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2303   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2304   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2305   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2306   //
2307   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2308   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2309   //
2310   MCAuto<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2311   MCAuto<DataArrayInt> faceIds=tmp->findIdsEqual(1); tmp=(DataArrayInt*)0;
2312   const int *revDescPtr=revDesc->getConstPointer();
2313   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2314   int nbOfCells=getNumberOfCells();
2315   std::vector<bool> ret1(nbOfCells,false);
2316   int sz=0;
2317   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2318     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2319       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2320   //
2321   DataArrayInt *ret2=DataArrayInt::New();
2322   ret2->alloc(sz,1);
2323   int *ret2Ptr=ret2->getPointer();
2324   sz=0;
2325   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2326     if(*it)
2327       *ret2Ptr++=sz;
2328   ret2->setName("BoundaryCells");
2329   return ret2;
2330 }
2331
2332 /*!
2333  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2334  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2335  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2336  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2337  *
2338  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2339  * 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
2340  * equals a cell in \b otherDimM1OnSameCoords.
2341  *
2342  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2343  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2344  *
2345  * \param [in] otherDimM1OnSameCoords
2346  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2347  * \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
2348  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2349  */
2350 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2351 {
2352   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2354   checkConnectivityFullyDefined();
2355   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2356   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2357     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2358   MCAuto<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2359   MCAuto<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2360   MCAuto<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2361   MCAuto<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2362   MCAuto<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2363   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2364   DataArrayInt *idsOtherInConsti=0;
2365   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2366   MCAuto<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2367   if(!b)
2368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2369   std::set<int> s1;
2370   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2371     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2372   MCAuto<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2373   s1arr_renum1->sort();
2374   cellIdsRk0=s0arr.retn();
2375   //cellIdsRk1=s_renum1.retn();
2376   cellIdsRk1=s1arr_renum1.retn();
2377 }
2378
2379 /*!
2380  * 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
2381  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2382  * 
2383  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2384  */
2385 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2386 {
2387   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2388   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2389   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2390   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2391   //
2392   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2393   revDesc=0; desc=0; descIndx=0;
2394   MCAuto<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2395   MCAuto<DataArrayInt> part=revDescIndx2->findIdsEqual(1);
2396   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2397 }
2398
2399 /*!
2400  * Finds nodes lying on the boundary of \a this mesh.
2401  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2402  *          nodes. The caller is to delete this array using decrRef() as it is no
2403  *          more needed.
2404  *  \throw If the coordinates array is not set.
2405  *  \throw If the nodal connectivity of cells is node defined.
2406  *
2407  *  \if ENABLE_EXAMPLES
2408  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2409  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2410  *  \endif
2411  */
2412 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2413 {
2414   MCAuto<MEDCouplingUMesh> skin=computeSkin();
2415   return skin->computeFetchedNodeIds();
2416 }
2417
2418 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2419 {
2420   incrRef();
2421   return const_cast<MEDCouplingUMesh *>(this);
2422 }
2423
2424 /*!
2425  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2426  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2427  * 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.
2428  * 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.
2429  * 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.
2430  *
2431  * \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
2432  *             parameter is altered during the call.
2433  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2434  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2435  * \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.
2436  *
2437  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2438  */
2439 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2440                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2441 {
2442   typedef MCAuto<DataArrayInt> DAInt;
2443   typedef MCAuto<MEDCouplingUMesh> MCUMesh;
2444
2445   checkFullyDefined();
2446   otherDimM1OnSameCoords.checkFullyDefined();
2447   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2448     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2449   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2450     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2451
2452   // Checking star-shaped M1 group:
2453   DAInt dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2454   MCUMesh meshM2 = otherDimM1OnSameCoords.buildDescendingConnectivity(dt0, dit0, rdt0, rdit0);
2455   DAInt dsi = rdit0->deltaShiftIndex();
2456   DAInt idsTmp0 = dsi->findIdsNotInRange(-1, 3);
2457   if(idsTmp0->getNumberOfTuples())
2458     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group: group is too complex: some points (or edges) have more than two connected segments (or faces)!");
2459   dt0=0; dit0=0; rdt0=0; rdit0=0; idsTmp0=0;
2460
2461   // Get extreme nodes from the group (they won't be duplicated), ie nodes belonging to boundary cells of M1
2462   DAInt xtremIdsM2 = dsi->findIdsEqual(1); dsi = 0;
2463   MCUMesh meshM2Part = static_cast<MEDCouplingUMesh *>(meshM2->buildPartOfMySelf(xtremIdsM2->begin(), xtremIdsM2->end(),true));
2464   DAInt xtrem = meshM2Part->computeFetchedNodeIds();
2465   // Remove from the list points on the boundary of the M0 mesh (those need duplication!)
2466   dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2467   MCUMesh m0desc = buildDescendingConnectivity(dt0, dit0, rdt0, rdit0); dt0=0; dit0=0; rdt0=0;
2468   dsi = rdit0->deltaShiftIndex();
2469   DAInt boundSegs = dsi->findIdsEqual(1);   // boundary segs/faces of the M0 mesh
2470   MCUMesh m0descSkin = static_cast<MEDCouplingUMesh *>(m0desc->buildPartOfMySelf(boundSegs->begin(),boundSegs->end(), true));
2471   DAInt fNodes = m0descSkin->computeFetchedNodeIds();
2472   // In 3D, some points on the boundary of M0 still need duplication:
2473   DAInt notDup = 0;
2474   if (getMeshDimension() == 3)
2475     {
2476       DAInt dnu1=DataArrayInt::New(), dnu2=DataArrayInt::New(), dnu3=DataArrayInt::New(), dnu4=DataArrayInt::New();
2477       MCUMesh m0descSkinDesc = m0descSkin->buildDescendingConnectivity(dnu1, dnu2, dnu3, dnu4);
2478       dnu1=0;dnu2=0;dnu3=0;dnu4=0;
2479       DataArrayInt * corresp=0;
2480       meshM2->areCellsIncludedIn(m0descSkinDesc,2,corresp);
2481       DAInt validIds = corresp->findIdsInRange(0, meshM2->getNumberOfCells());
2482       corresp->decrRef();
2483       if (validIds->getNumberOfTuples())
2484         {
2485           MCUMesh m1IntersecSkin = static_cast<MEDCouplingUMesh *>(m0descSkinDesc->buildPartOfMySelf(validIds->begin(), validIds->end(), true));
2486           DAInt notDuplSkin = m1IntersecSkin->findBoundaryNodes();
2487           DAInt fNodes1 = fNodes->buildSubstraction(notDuplSkin);
2488           notDup = xtrem->buildSubstraction(fNodes1);
2489         }
2490       else
2491         notDup = xtrem->buildSubstraction(fNodes);
2492     }
2493   else
2494     notDup = xtrem->buildSubstraction(fNodes);
2495
2496   // Now compute cells around group (i.e. cells where we will do the propagation to identify the two sub-sets delimited by the group)
2497   DAInt m1Nodes = otherDimM1OnSameCoords.computeFetchedNodeIds();
2498   DAInt dupl = m1Nodes->buildSubstraction(notDup);
2499   DAInt cellsAroundGroup = getCellIdsLyingOnNodes(dupl->begin(), dupl->end(), false);  // false= take cell in, even if not all nodes are in notDup
2500
2501   //
2502   MCUMesh m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellsAroundGroup->begin(),cellsAroundGroup->end(),true));
2503   int nCells2 = m0Part2->getNumberOfCells();
2504   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2505   MCUMesh m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2506
2507   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2508   DataArrayInt *tmp00=0,*tmp11=0;
2509   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2510   DAInt neighInit00(tmp00);
2511   DAInt neighIInit00(tmp11);
2512   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2513   DataArrayInt *idsTmp=0;
2514   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2515   DAInt ids(idsTmp);
2516   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2517   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2518   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2519   DataArrayInt *tmp0=0,*tmp1=0;
2520   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2521   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2522   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2523   DAInt neigh00(tmp0);
2524   DAInt neighI00(tmp1);
2525
2526   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2527   int seed = 0, nIter = 0;
2528   int nIterMax = nCells2+1; // Safety net for the loop
2529   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2530   hitCells->fillWithValue(-1);
2531   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2532   cellsToModifyConn0_torenum->alloc(0,1);
2533   while (nIter < nIterMax)
2534     {
2535       DAInt t = hitCells->findIdsEqual(-1);
2536       if (!t->getNumberOfTuples())
2537         break;
2538       // Connex zone without the crack (to compute the next seed really)
2539       int dnu;
2540       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2541       int cnt = 0;
2542       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2543         hitCells->setIJ(*ptr,0,1);
2544       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2545       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2546       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2547       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2548       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2549       DAInt nonHitCells = hitCells->findIdsEqual(-1);
2550       DAInt intersec = nonHitCells->buildIntersection(comple);
2551       if (intersec->getNumberOfTuples())
2552         { seed = intersec->getIJ(0,0); }
2553       else
2554         { break; }
2555       nIter++;
2556     }
2557   if (nIter >= nIterMax)
2558     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2559
2560   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2561   cellsToModifyConn0_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2562   cellsToModifyConn1_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2563   //
2564   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2565   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2566   nodeIdsToDuplicate=dupl.retn();
2567 }
2568
2569 /*!
2570  * This method operates a modification of the connectivity and coords in \b this.
2571  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2572  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2573  * 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
2574  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2575  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2576  * 
2577  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2578  * 
2579  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2580  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2581  */
2582 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2583 {
2584   int nbOfNodes=getNumberOfNodes();
2585   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2586   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2587 }
2588
2589 /*!
2590  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2591  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2592  *
2593  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2594  *
2595  * \sa renumberNodesInConn
2596  */
2597 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2598 {
2599   checkConnectivityFullyDefined();
2600   int *conn(getNodalConnectivity()->getPointer());
2601   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2602   int nbOfCells(getNumberOfCells());
2603   for(int i=0;i<nbOfCells;i++)
2604     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2605       {
2606         int& node=conn[iconn];
2607         if(node>=0)//avoid polyhedron separator
2608           {
2609             node+=offset;
2610           }
2611       }
2612   _nodal_connec->declareAsNew();
2613   updateTime();
2614 }
2615
2616 /*!
2617  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2618  *  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
2619  *  of a big mesh.
2620  */
2621 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2622 {
2623   checkConnectivityFullyDefined();
2624   int *conn(getNodalConnectivity()->getPointer());
2625   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2626   int nbOfCells(getNumberOfCells());
2627   for(int i=0;i<nbOfCells;i++)
2628     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2629       {
2630         int& node=conn[iconn];
2631         if(node>=0)//avoid polyhedron separator
2632           {
2633             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2634             if(it!=newNodeNumbersO2N.end())
2635               {
2636                 node=(*it).second;
2637               }
2638             else
2639               {
2640                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2641                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2642               }
2643           }
2644       }
2645   _nodal_connec->declareAsNew();
2646   updateTime();
2647 }
2648
2649 /*!
2650  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2651  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2652  * This method is a generalization of shiftNodeNumbersInConn().
2653  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2654  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2655  *         this->getNumberOfNodes(), in "Old to New" mode. 
2656  *         See \ref numbering for more info on renumbering modes.
2657  *  \throw If the nodal connectivity of cells is not defined.
2658  *
2659  *  \if ENABLE_EXAMPLES
2660  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2661  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2662  *  \endif
2663  */
2664 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2665 {
2666   checkConnectivityFullyDefined();
2667   int *conn=getNodalConnectivity()->getPointer();
2668   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2669   int nbOfCells(getNumberOfCells());
2670   for(int i=0;i<nbOfCells;i++)
2671     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2672       {
2673         int& node=conn[iconn];
2674         if(node>=0)//avoid polyhedron separator
2675           {
2676             node=newNodeNumbersO2N[node];
2677           }
2678       }
2679   _nodal_connec->declareAsNew();
2680   updateTime();
2681 }
2682
2683 /*!
2684  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2685  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2686  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2687  * 
2688  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2689  */
2690 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
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+=delta;
2703           }
2704       }
2705   _nodal_connec->declareAsNew();
2706   updateTime();
2707 }
2708
2709 /*!
2710  * This method operates a modification of the connectivity in \b this.
2711  * 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.
2712  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2713  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2714  * 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
2715  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2716  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2717  * 
2718  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2719  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2720  * 
2721  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2722  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2723  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2724  */
2725 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2726 {
2727   checkConnectivityFullyDefined();
2728   std::map<int,int> m;
2729   int val=offset;
2730   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2731     m[*work]=val;
2732   int *conn=getNodalConnectivity()->getPointer();
2733   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2734   int nbOfCells=getNumberOfCells();
2735   for(int i=0;i<nbOfCells;i++)
2736     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2737       {
2738         int& node=conn[iconn];
2739         if(node>=0)//avoid polyhedron separator
2740           {
2741             std::map<int,int>::iterator it=m.find(node);
2742             if(it!=m.end())
2743               node=(*it).second;
2744           }
2745       }
2746   updateTime();
2747 }
2748
2749 /*!
2750  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2751  *
2752  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2753  * After the call of this method the number of cells remains the same as before.
2754  *
2755  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2756  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2757  * be strictly in [0;this->getNumberOfCells()).
2758  *
2759  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2760  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2761  * should be contained in[0;this->getNumberOfCells()).
2762  * 
2763  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2764  * \param check
2765  */
2766 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2767 {
2768   checkConnectivityFullyDefined();
2769   int nbCells=getNumberOfCells();
2770   const int *array=old2NewBg;
2771   if(check)
2772     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2773   //
2774   const int *conn=_nodal_connec->getConstPointer();
2775   const int *connI=_nodal_connec_index->getConstPointer();
2776   MCAuto<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2777   MCAuto<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2778   const int *n2oPtr=n2o->begin();
2779   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
2780   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2781   newConn->copyStringInfoFrom(*_nodal_connec);
2782   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
2783   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2784   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2785   //
2786   int *newC=newConn->getPointer();
2787   int *newCI=newConnI->getPointer();
2788   int loc=0;
2789   newCI[0]=loc;
2790   for(int i=0;i<nbCells;i++)
2791     {
2792       int pos=n2oPtr[i];
2793       int nbOfElts=connI[pos+1]-connI[pos];
2794       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2795       loc+=nbOfElts;
2796       newCI[i+1]=loc;
2797     }
2798   //
2799   setConnectivity(newConn,newConnI);
2800   if(check)
2801     free(const_cast<int *>(array));
2802 }
2803
2804 /*!
2805  * Finds cells whose bounding boxes intersect a given bounding box.
2806  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2807  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2808  *         zMax (if in 3D). 
2809  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2810  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2811  *         extent of the bounding box of cell to produce an addition to this bounding box.
2812  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2813  *         cells. The caller is to delete this array using decrRef() as it is no more
2814  *         needed. 
2815  *  \throw If the coordinates array is not set.
2816  *  \throw If the nodal connectivity of cells is not defined.
2817  *
2818  *  \if ENABLE_EXAMPLES
2819  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2820  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2821  *  \endif
2822  */
2823 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2824 {
2825   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2826   if(getMeshDimension()==-1)
2827     {
2828       elems->pushBackSilent(0);
2829       return elems.retn();
2830     }
2831   int dim=getSpaceDimension();
2832   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2833   const int* conn      = getNodalConnectivity()->getConstPointer();
2834   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2835   const double* coords = getCoords()->getConstPointer();
2836   int nbOfCells=getNumberOfCells();
2837   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2838     {
2839       for (int i=0; i<dim; i++)
2840         {
2841           elem_bb[i*2]=std::numeric_limits<double>::max();
2842           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2843         }
2844
2845       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2846         {
2847           int node= conn[inode];
2848           if(node>=0)//avoid polyhedron separator
2849             {
2850               for (int idim=0; idim<dim; idim++)
2851                 {
2852                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2853                     {
2854                       elem_bb[idim*2] = coords[node*dim+idim] ;
2855                     }
2856                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2857                     {
2858                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2859                     }
2860                 }
2861             }
2862         }
2863       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2864         elems->pushBackSilent(ielem);
2865     }
2866   return elems.retn();
2867 }
2868
2869 /*!
2870  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2871  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2872  * added in 'elems' parameter.
2873  */
2874 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2875 {
2876   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2877   if(getMeshDimension()==-1)
2878     {
2879       elems->pushBackSilent(0);
2880       return elems.retn();
2881     }
2882   int dim=getSpaceDimension();
2883   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2884   const int* conn      = getNodalConnectivity()->getConstPointer();
2885   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2886   const double* coords = getCoords()->getConstPointer();
2887   int nbOfCells=getNumberOfCells();
2888   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2889     {
2890       for (int i=0; i<dim; i++)
2891         {
2892           elem_bb[i*2]=std::numeric_limits<double>::max();
2893           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2894         }
2895
2896       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2897         {
2898           int node= conn[inode];
2899           if(node>=0)//avoid polyhedron separator
2900             {
2901               for (int idim=0; idim<dim; idim++)
2902                 {
2903                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2904                     {
2905                       elem_bb[idim*2] = coords[node*dim+idim] ;
2906                     }
2907                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2908                     {
2909                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2910                     }
2911                 }
2912             }
2913         }
2914       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2915         elems->pushBackSilent(ielem);
2916     }
2917   return elems.retn();
2918 }
2919
2920 /*!
2921  * Returns a type of a cell by its id.
2922  *  \param [in] cellId - the id of the cell of interest.
2923  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2924  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2925  */
2926 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2927 {
2928   const int *ptI=_nodal_connec_index->getConstPointer();
2929   const int *pt=_nodal_connec->getConstPointer();
2930   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2931     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2932   else
2933     {
2934       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2935       throw INTERP_KERNEL::Exception(oss.str().c_str());
2936     }
2937 }
2938
2939 /*!
2940  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2941  * This method does not throw exception if geometric type \a type is not in \a this.
2942  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2943  * The coordinates array is not considered here.
2944  *
2945  * \param [in] type the geometric type
2946  * \return cell ids in this having geometric type \a type.
2947  */
2948 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2949 {
2950
2951   MCAuto<DataArrayInt> ret=DataArrayInt::New();
2952   ret->alloc(0,1);
2953   checkConnectivityFullyDefined();
2954   int nbCells=getNumberOfCells();
2955   int mdim=getMeshDimension();
2956   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2957   if(mdim!=(int)cm.getDimension())
2958     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2959   const int *ptI=_nodal_connec_index->getConstPointer();
2960   const int *pt=_nodal_connec->getConstPointer();
2961   for(int i=0;i<nbCells;i++)
2962     {
2963       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2964         ret->pushBackSilent(i);
2965     }
2966   return ret.retn();
2967 }
2968
2969 /*!
2970  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2971  */
2972 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2973 {
2974   const int *ptI=_nodal_connec_index->getConstPointer();
2975   const int *pt=_nodal_connec->getConstPointer();
2976   int nbOfCells=getNumberOfCells();
2977   int ret=0;
2978   for(int i=0;i<nbOfCells;i++)
2979     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2980       ret++;
2981   return ret;
2982 }
2983
2984 /*!
2985  * Returns the nodal connectivity of a given cell.
2986  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2987  * all returned node ids can be used in getCoordinatesOfNode().
2988  *  \param [in] cellId - an id of the cell of interest.
2989  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2990  *         cleared before the appending.
2991  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2992  */
2993 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2994 {
2995   const int *ptI=_nodal_connec_index->getConstPointer();
2996   const int *pt=_nodal_connec->getConstPointer();
2997   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2998     if(*w>=0)
2999       conn.push_back(*w);
3000 }
3001
3002 std::string MEDCouplingUMesh::simpleRepr() const
3003 {
3004   static const char msg0[]="No coordinates specified !";
3005   std::ostringstream ret;
3006   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
3007   ret << "Description of mesh : \"" << getDescription() << "\"\n";
3008   int tmpp1,tmpp2;
3009   double tt=getTime(tmpp1,tmpp2);
3010   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
3011   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
3012   if(_mesh_dim>=-1)
3013     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
3014   else
3015     { ret << " Mesh dimension has not been set or is invalid !"; }
3016   if(_coords!=0)
3017     {
3018       const int spaceDim=getSpaceDimension();
3019       ret << spaceDim << "\nInfo attached on space dimension : ";
3020       for(int i=0;i<spaceDim;i++)
3021         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3022       ret << "\n";
3023     }
3024   else
3025     ret << msg0 << "\n";
3026   ret << "Number of nodes : ";
3027   if(_coords!=0)
3028     ret << getNumberOfNodes() << "\n";
3029   else
3030     ret << msg0 << "\n";
3031   ret << "Number of cells : ";
3032   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3033     ret << getNumberOfCells() << "\n";
3034   else
3035     ret << "No connectivity specified !" << "\n";
3036   ret << "Cell types present : ";
3037   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3038     {
3039       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3040       ret << cm.getRepr() << " ";
3041     }
3042   ret << "\n";
3043   return ret.str();
3044 }
3045
3046 std::string MEDCouplingUMesh::advancedRepr() const
3047 {
3048   std::ostringstream ret;
3049   ret << simpleRepr();
3050   ret << "\nCoordinates array : \n___________________\n\n";
3051   if(_coords)
3052     _coords->reprWithoutNameStream(ret);
3053   else
3054     ret << "No array set !\n";
3055   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3056   reprConnectivityOfThisLL(ret);
3057   return ret.str();
3058 }
3059
3060 /*!
3061  * This method returns a C++ code that is a dump of \a this.
3062  * This method will throw if this is not fully defined.
3063  */
3064 std::string MEDCouplingUMesh::cppRepr() const
3065 {
3066   static const char coordsName[]="coords";
3067   static const char connName[]="conn";
3068   static const char connIName[]="connI";
3069   checkFullyDefined();
3070   std::ostringstream ret; ret << "// coordinates" << std::endl;
3071   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3072   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3073   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3074   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3075   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3076   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3077   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3078   return ret.str();
3079 }
3080
3081 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3082 {
3083   std::ostringstream ret;
3084   reprConnectivityOfThisLL(ret);
3085   return ret.str();
3086 }
3087
3088 /*!
3089  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3090  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3091  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3092  * some algos).
3093  * 
3094  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3095  * 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
3096  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3097  */
3098 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3099 {
3100   int mdim=getMeshDimension();
3101   if(mdim<0)
3102     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3103   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3104   MCAuto<DataArrayInt> tmp1,tmp2;
3105   bool needToCpyCT=true;
3106   if(!_nodal_connec)
3107     {
3108       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3109       needToCpyCT=false;
3110     }
3111   else
3112     {
3113       tmp1=_nodal_connec;
3114       tmp1->incrRef();
3115     }
3116   if(!_nodal_connec_index)
3117     {
3118       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3119       needToCpyCT=false;
3120     }
3121   else
3122     {
3123       tmp2=_nodal_connec_index;
3124       tmp2->incrRef();
3125     }
3126   ret->setConnectivity(tmp1,tmp2,false);
3127   if(needToCpyCT)
3128     ret->_types=_types;
3129   if(!_coords)
3130     {
3131       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3132       ret->setCoords(coords);
3133     }
3134   else
3135     ret->setCoords(_coords);
3136   return ret.retn();
3137 }
3138
3139 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3140 {
3141   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3142     {
3143       int nbOfCells=getNumberOfCells();
3144       const int *c=_nodal_connec->getConstPointer();
3145       const int *ci=_nodal_connec_index->getConstPointer();
3146       for(int i=0;i<nbOfCells;i++)
3147         {
3148           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3149           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3150           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3151           stream << "\n";
3152         }
3153     }
3154   else
3155     stream << "Connectivity not defined !\n";
3156 }
3157
3158 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3159 {
3160   const int *ptI=_nodal_connec_index->getConstPointer();
3161   const int *pt=_nodal_connec->getConstPointer();
3162   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3163     return ptI[cellId+1]-ptI[cellId]-1;
3164   else
3165     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3166 }
3167
3168 /*!
3169  * Returns types of cells of the specified part of \a this mesh.
3170  * This method avoids computing sub-mesh explicitely to get its types.
3171  *  \param [in] begin - an array of cell ids of interest.
3172  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3173  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3174  *         describing the cell types. 
3175  *  \throw If the coordinates array is not set.
3176  *  \throw If the nodal connectivity of cells is not defined.
3177  *  \sa getAllGeoTypes()
3178  */
3179 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3180 {
3181   checkFullyDefined();
3182   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3183   const int *conn=_nodal_connec->getConstPointer();
3184   const int *connIndex=_nodal_connec_index->getConstPointer();
3185   for(const int *w=begin;w!=end;w++)
3186     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3187   return ret;
3188 }
3189
3190 /*!
3191  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3192  * Optionally updates
3193  * a set of types of cells constituting \a this mesh. 
3194  * This method is for advanced users having prepared their connectivity before. For
3195  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3196  *  \param [in] conn - the nodal connectivity array. 
3197  *  \param [in] connIndex - the nodal connectivity index array.
3198  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3199  *         mesh is updated.
3200  */
3201 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3202 {
3203   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3204   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3205   if(isComputingTypes)
3206     computeTypes();
3207   declareAsNew();
3208 }
3209
3210 /*!
3211  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3212  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3213  */
3214 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3215     _nodal_connec(0),_nodal_connec_index(0),
3216     _types(other._types)
3217 {
3218   if(other._nodal_connec)
3219     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCopy);
3220   if(other._nodal_connec_index)
3221     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCopy);
3222 }
3223
3224 MEDCouplingUMesh::~MEDCouplingUMesh()
3225 {
3226   if(_nodal_connec)
3227     _nodal_connec->decrRef();
3228   if(_nodal_connec_index)
3229     _nodal_connec_index->decrRef();
3230 }
3231
3232 /*!
3233  * Recomputes a set of cell types of \a this mesh. For more info see
3234  * \ref MEDCouplingUMeshNodalConnectivity.
3235  */
3236 void MEDCouplingUMesh::computeTypes()
3237 {
3238   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3239 }
3240
3241 /*!
3242  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3243  */
3244 void MEDCouplingUMesh::checkFullyDefined() const
3245 {
3246   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3247     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3248 }
3249
3250 /*!
3251  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3252  */
3253 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3254 {
3255   if(!_nodal_connec_index || !_nodal_connec)
3256     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3257 }
3258
3259 /*!
3260  * Returns a number of cells constituting \a this mesh. 
3261  *  \return int - the number of cells in \a this mesh.
3262  *  \throw If the nodal connectivity of cells is not defined.
3263  */
3264 int MEDCouplingUMesh::getNumberOfCells() const
3265
3266   if(_nodal_connec_index)
3267     return _nodal_connec_index->getNumberOfTuples()-1;
3268   else
3269     if(_mesh_dim==-1)
3270       return 1;
3271     else
3272       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3273 }
3274
3275 /*!
3276  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3277  * mesh. For more info see \ref meshes.
3278  *  \return int - the dimension of \a this mesh.
3279  *  \throw If the mesh dimension is not defined using setMeshDimension().
3280  */
3281 int MEDCouplingUMesh::getMeshDimension() const
3282 {
3283   if(_mesh_dim<-1)
3284     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3285   return _mesh_dim;
3286 }
3287
3288 /*!
3289  * Returns a length of the nodal connectivity array.
3290  * This method is for test reason. Normally the integer returned is not useable by
3291  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3292  *  \return int - the length of the nodal connectivity array.
3293  */
3294 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3295 {
3296   return _nodal_connec->getNbOfElems();
3297 }
3298
3299 /*!
3300  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3301  */
3302 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3303 {
3304   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3305   tinyInfo.push_back(getMeshDimension());
3306   tinyInfo.push_back(getNumberOfCells());
3307   if(_nodal_connec)
3308     tinyInfo.push_back(getNodalConnectivityArrayLen());
3309   else
3310     tinyInfo.push_back(-1);
3311 }
3312
3313 /*!
3314  * First step of unserialization process.
3315  */
3316 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3317 {
3318   return tinyInfo[6]<=0;
3319 }
3320
3321 /*!
3322  * Second step of serialization process.
3323  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3324  * \param a1
3325  * \param a2
3326  * \param littleStrings
3327  */
3328 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3329 {
3330   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3331   if(tinyInfo[5]!=-1)
3332     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3333 }
3334
3335 /*!
3336  * Third and final step of serialization process.
3337  */
3338 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3339 {
3340   MEDCouplingPointSet::serialize(a1,a2);
3341   if(getMeshDimension()>-1)
3342     {
3343       a1=DataArrayInt::New();
3344       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3345       int *ptA1=a1->getPointer();
3346       const int *conn=getNodalConnectivity()->getConstPointer();
3347       const int *index=getNodalConnectivityIndex()->getConstPointer();
3348       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3349       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3350     }
3351   else
3352     a1=0;
3353 }
3354
3355 /*!
3356  * Second and final unserialization process.
3357  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3358  */
3359 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3360 {
3361   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3362   setMeshDimension(tinyInfo[5]);
3363   if(tinyInfo[7]!=-1)
3364     {
3365       // Connectivity
3366       const int *recvBuffer=a1->getConstPointer();
3367       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3368       myConnecIndex->alloc(tinyInfo[6]+1,1);
3369       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3370       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3371       myConnec->alloc(tinyInfo[7],1);
3372       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3373       setConnectivity(myConnec, myConnecIndex);
3374     }
3375 }
3376
3377 /*!
3378  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelfSlice.
3379  * CellIds are given using range specified by a start an end and step.
3380  */
3381 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice(int start, int end, int step) const
3382 {
3383   checkFullyDefined();
3384   int ncell=getNumberOfCells();
3385   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3386   ret->_mesh_dim=_mesh_dim;
3387   ret->setCoords(_coords);
3388   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : ");
3389   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3390   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3391   int work=start;
3392   const int *conn=_nodal_connec->getConstPointer();
3393   const int *connIndex=_nodal_connec_index->getConstPointer();
3394   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3395     {
3396       if(work>=0 && work<ncell)
3397         {
3398           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3399         }
3400       else
3401         {
3402           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3403           throw INTERP_KERNEL::Exception(oss.str().c_str());
3404         }
3405     }
3406   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3407   int *newConnPtr=newConn->getPointer();
3408   std::set<INTERP_KERNEL::NormalizedCellType> types;
3409   work=start;
3410   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3411     {
3412       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3413       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3414     }
3415   ret->setConnectivity(newConn,newConnI,false);
3416   ret->_types=types;
3417   ret->copyTinyInfoFrom(this);
3418   return ret.retn();
3419 }
3420
3421 /*!
3422  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3423  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3424  * The return newly allocated mesh will share the same coordinates as \a this.
3425  */
3426 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3427 {
3428   checkConnectivityFullyDefined();
3429   int ncell=getNumberOfCells();
3430   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3431   ret->_mesh_dim=_mesh_dim;
3432   ret->setCoords(_coords);
3433   std::size_t nbOfElemsRet=std::distance(begin,end);
3434   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3435   connIndexRet[0]=0;
3436   const int *conn=_nodal_connec->getConstPointer();
3437   const int *connIndex=_nodal_connec_index->getConstPointer();
3438   int newNbring=0;
3439   for(const int *work=begin;work!=end;work++,newNbring++)
3440     {
3441       if(*work>=0 && *work<ncell)
3442         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3443       else
3444         {
3445           free(connIndexRet);
3446           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3447           throw INTERP_KERNEL::Exception(oss.str().c_str());
3448         }
3449     }
3450   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3451   int *connRetWork=connRet;
3452   std::set<INTERP_KERNEL::NormalizedCellType> types;
3453   for(const int *work=begin;work!=end;work++)
3454     {
3455       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3456       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3457     }
3458   MCAuto<DataArrayInt> connRetArr=DataArrayInt::New();
3459   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3460   MCAuto<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3461   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3462   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3463   ret->_types=types;
3464   ret->copyTinyInfoFrom(this);
3465   return ret.retn();
3466 }
3467
3468 /*!
3469  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3470  * mesh.<br>
3471  * For 1D cells, the returned field contains lengths.<br>
3472  * For 2D cells, the returned field contains areas.<br>
3473  * For 3D cells, the returned field contains volumes.
3474  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3475  *         orientation, i.e. the volume is always positive.
3476  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3477  *         and one time . The caller is to delete this field using decrRef() as it is no
3478  *         more needed.
3479  */
3480 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3481 {
3482   std::string name="MeasureOfMesh_";
3483   name+=getName();
3484   int nbelem=getNumberOfCells();
3485   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3486   field->setName(name);
3487   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3488   array->alloc(nbelem,1);
3489   double *area_vol=array->getPointer();
3490   field->setArray(array) ; array=0;
3491   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3492   field->synchronizeTimeWithMesh();
3493   if(getMeshDimension()!=-1)
3494     {
3495       int ipt;
3496       INTERP_KERNEL::NormalizedCellType type;
3497       int dim_space=getSpaceDimension();
3498       const double *coords=getCoords()->getConstPointer();
3499       const int *connec=getNodalConnectivity()->getConstPointer();
3500       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3501       for(int iel=0;iel<nbelem;iel++)
3502         {
3503           ipt=connec_index[iel];
3504           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3505           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);
3506         }
3507       if(isAbs)
3508         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3509     }
3510   else
3511     {
3512       area_vol[0]=std::numeric_limits<double>::max();
3513     }
3514   return field.retn();
3515 }
3516
3517 /*!
3518  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3519  * mesh.<br>
3520  * For 1D cells, the returned array contains lengths.<br>
3521  * For 2D cells, the returned array contains areas.<br>
3522  * For 3D cells, the returned array contains volumes.
3523  * This method avoids building explicitly a part of \a this mesh to perform the work.
3524  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3525  *         orientation, i.e. the volume is always positive.
3526  *  \param [in] begin - an array of cell ids of interest.
3527  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3528  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3529  *          delete this array using decrRef() as it is no more needed.
3530  * 
3531  *  \if ENABLE_EXAMPLES
3532  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3533  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3534  *  \endif
3535  *  \sa getMeasureField()
3536  */
3537 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3538 {
3539   std::string name="PartMeasureOfMesh_";
3540   name+=getName();
3541   int nbelem=(int)std::distance(begin,end);
3542   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3543   array->setName(name);
3544   array->alloc(nbelem,1);
3545   double *area_vol=array->getPointer();
3546   if(getMeshDimension()!=-1)
3547     {
3548       int ipt;
3549       INTERP_KERNEL::NormalizedCellType type;
3550       int dim_space=getSpaceDimension();
3551       const double *coords=getCoords()->getConstPointer();
3552       const int *connec=getNodalConnectivity()->getConstPointer();
3553       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3554       for(const int *iel=begin;iel!=end;iel++)
3555         {
3556           ipt=connec_index[*iel];
3557           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3558           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3559         }
3560       if(isAbs)
3561         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3562     }
3563   else
3564     {
3565       area_vol[0]=std::numeric_limits<double>::max();
3566     }
3567   return array.retn();
3568 }
3569
3570 /*!
3571  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3572  * \a this one. The returned field contains the dual cell volume for each corresponding
3573  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3574  *  the dual mesh in P1 sens of \a this.<br>
3575  * For 1D cells, the returned field contains lengths.<br>
3576  * For 2D cells, the returned field contains areas.<br>
3577  * For 3D cells, the returned field contains volumes.
3578  * This method is useful to check "P1*" conservative interpolators.
3579  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3580  *         orientation, i.e. the volume is always positive.
3581  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3582  *          nodes and one time. The caller is to delete this array using decrRef() as
3583  *          it is no more needed.
3584  */
3585 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3586 {
3587   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3588   std::string name="MeasureOnNodeOfMesh_";
3589   name+=getName();
3590   int nbNodes=getNumberOfNodes();
3591   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3592   double cst=1./((double)getMeshDimension()+1.);
3593   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3594   array->alloc(nbNodes,1);
3595   double *valsToFill=array->getPointer();
3596   std::fill(valsToFill,valsToFill+nbNodes,0.);
3597   const double *values=tmp->getArray()->getConstPointer();
3598   MCAuto<DataArrayInt> da=DataArrayInt::New();
3599   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3600   getReverseNodalConnectivity(da,daInd);
3601   const int *daPtr=da->getConstPointer();
3602   const int *daIPtr=daInd->getConstPointer();
3603   for(int i=0;i<nbNodes;i++)
3604     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3605       valsToFill[i]+=cst*values[*cell];
3606   ret->setMesh(this);
3607   ret->setArray(array);
3608   return ret.retn();
3609 }
3610
3611 /*!
3612  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3613  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3614  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3615  * and are normalized.
3616  * <br> \a this can be either 
3617  * - a  2D mesh in 2D or 3D space or 
3618  * - an 1D mesh in 2D space.
3619  * 
3620  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3621  *          cells and one time. The caller is to delete this field using decrRef() as
3622  *          it is no more needed.
3623  *  \throw If the nodal connectivity of cells is not defined.
3624  *  \throw If the coordinates array is not set.
3625  *  \throw If the mesh dimension is not set.
3626  *  \throw If the mesh and space dimension is not as specified above.
3627  */
3628 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3629 {
3630   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3631     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3632   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3633   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3634   int nbOfCells=getNumberOfCells();
3635   int nbComp=getMeshDimension()+1;
3636   array->alloc(nbOfCells,nbComp);
3637   double *vals=array->getPointer();
3638   const int *connI=_nodal_connec_index->getConstPointer();
3639   const int *conn=_nodal_connec->getConstPointer();
3640   const double *coords=_coords->getConstPointer();
3641   if(getMeshDimension()==2)
3642     {
3643       if(getSpaceDimension()==3)
3644         {
3645           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3646           const double *locPtr=loc->getConstPointer();
3647           for(int i=0;i<nbOfCells;i++,vals+=3)
3648             {
3649               int offset=connI[i];
3650               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3651               double n=INTERP_KERNEL::norm<3>(vals);
3652               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3653             }
3654         }
3655       else
3656         {
3657           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3658           const double *isAbsPtr=isAbs->getArray()->begin();
3659           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3660             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3661         }
3662     }
3663   else//meshdimension==1
3664     {
3665       double tmp[2];
3666       for(int i=0;i<nbOfCells;i++)
3667         {
3668           int offset=connI[i];
3669           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3670           double n=INTERP_KERNEL::norm<2>(tmp);
3671           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3672           *vals++=-tmp[1];
3673           *vals++=tmp[0];
3674         }
3675     }
3676   ret->setArray(array);
3677   ret->setMesh(this);
3678   ret->synchronizeTimeWithSupport();
3679   return ret.retn();
3680 }
3681
3682 /*!
3683  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3684  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3685  * and are normalized.
3686  * <br> \a this can be either 
3687  * - a  2D mesh in 2D or 3D space or 
3688  * - an 1D mesh in 2D space.
3689  * 
3690  * This method avoids building explicitly a part of \a this mesh to perform the work.
3691  *  \param [in] begin - an array of cell ids of interest.
3692  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3693  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3694  *          cells and one time. The caller is to delete this field using decrRef() as
3695  *          it is no more needed.
3696  *  \throw If the nodal connectivity of cells is not defined.
3697  *  \throw If the coordinates array is not set.
3698  *  \throw If the mesh dimension is not set.
3699  *  \throw If the mesh and space dimension is not as specified above.
3700  *  \sa buildOrthogonalField()
3701  *
3702  *  \if ENABLE_EXAMPLES
3703  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3704  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3705  *  \endif
3706  */
3707 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3708 {
3709   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3710     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3711   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3712   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3713   std::size_t nbelems=std::distance(begin,end);
3714   int nbComp=getMeshDimension()+1;
3715   array->alloc((int)nbelems,nbComp);
3716   double *vals=array->getPointer();
3717   const int *connI=_nodal_connec_index->getConstPointer();
3718   const int *conn=_nodal_connec->getConstPointer();
3719   const double *coords=_coords->getConstPointer();
3720   if(getMeshDimension()==2)
3721     {
3722       if(getSpaceDimension()==3)
3723         {
3724           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3725           const double *locPtr=loc->getConstPointer();
3726           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3727             {
3728               int offset=connI[*i];
3729               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3730               double n=INTERP_KERNEL::norm<3>(vals);
3731               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3732             }
3733         }
3734       else
3735         {
3736           for(std::size_t i=0;i<nbelems;i++)
3737             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3738         }
3739     }
3740   else//meshdimension==1
3741     {
3742       double tmp[2];
3743       for(const int *i=begin;i!=end;i++)
3744         {
3745           int offset=connI[*i];
3746           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3747           double n=INTERP_KERNEL::norm<2>(tmp);
3748           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3749           *vals++=-tmp[1];
3750           *vals++=tmp[0];
3751         }
3752     }
3753   ret->setArray(array);
3754   ret->setMesh(this);
3755   ret->synchronizeTimeWithSupport();
3756   return ret.retn();
3757 }
3758
3759 /*!
3760  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3761  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3762  * and are \b not normalized.
3763  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3764  *          cells and one time. The caller is to delete this field using decrRef() as
3765  *          it is no more needed.
3766  *  \throw If the nodal connectivity of cells is not defined.
3767  *  \throw If the coordinates array is not set.
3768  *  \throw If \a this->getMeshDimension() != 1.
3769  *  \throw If \a this mesh includes cells of type other than SEG2.
3770  */
3771 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3772 {
3773   if(getMeshDimension()!=1)
3774     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3775   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3776     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3777   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3778   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3779   int nbOfCells=getNumberOfCells();
3780   int spaceDim=getSpaceDimension();
3781   array->alloc(nbOfCells,spaceDim);
3782   double *pt=array->getPointer();
3783   const double *coo=getCoords()->getConstPointer();
3784   std::vector<int> conn;
3785   conn.reserve(2);
3786   for(int i=0;i<nbOfCells;i++)
3787     {
3788       conn.resize(0);
3789       getNodeIdsOfCell(i,conn);
3790       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3791     }
3792   ret->setArray(array);
3793   ret->setMesh(this);
3794   ret->synchronizeTimeWithSupport();
3795   return ret.retn();
3796 }
3797
3798 /*!
3799  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3800  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3801  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3802  * from. If a result face is shared by two 3D cells, then the face in included twice in
3803  * the result mesh.
3804  *  \param [in] origin - 3 components of a point defining location of the plane.
3805  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3806  *         must be greater than 1e-6.
3807  *  \param [in] eps - half-thickness of the plane.
3808  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3809  *         producing correspondent 2D cells. The caller is to delete this array
3810  *         using decrRef() as it is no more needed.
3811  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3812  *         not share the node coordinates array with \a this mesh. The caller is to
3813  *         delete this mesh using decrRef() as it is no more needed.  
3814  *  \throw If the coordinates array is not set.
3815  *  \throw If the nodal connectivity of cells is not defined.
3816  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3817  *  \throw If magnitude of \a vec is less than 1e-6.
3818  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3819  *  \throw If \a this includes quadratic cells.
3820  */
3821 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3822 {
3823   checkFullyDefined();
3824   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3825     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3826   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3827   if(candidates->empty())
3828     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3829   std::vector<int> nodes;
3830   DataArrayInt *cellIds1D=0;
3831   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3832   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3833   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3834   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3835   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3836   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3837   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3838   revDesc2=0; revDescIndx2=0;
3839   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3840   revDesc1=0; revDescIndx1=0;
3841   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3842   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3843   //
3844   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3845   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3846     cut3DCurve[*it]=-1;
3847   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3848   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3849   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3850                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3851                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3852   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3853   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3854   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3855   if(cellIds2->empty())
3856     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3857   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3858   ret->setCoords(mDesc1->getCoords());
3859   ret->setConnectivity(conn,connI,true);
3860   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3861   return ret.retn();
3862 }
3863
3864 /*!
3865  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3866 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
3867 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3868 the result mesh.
3869  *  \param [in] origin - 3 components of a point defining location of the plane.
3870  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3871  *         must be greater than 1e-6.
3872  *  \param [in] eps - half-thickness of the plane.
3873  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3874  *         producing correspondent segments. The caller is to delete this array
3875  *         using decrRef() as it is no more needed.
3876  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3877  *         mesh in 3D space. This mesh does not share the node coordinates array with
3878  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3879  *         no more needed. 
3880  *  \throw If the coordinates array is not set.
3881  *  \throw If the nodal connectivity of cells is not defined.
3882  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3883  *  \throw If magnitude of \a vec is less than 1e-6.
3884  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3885  *  \throw If \a this includes quadratic cells.
3886  */
3887 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3888 {
3889   checkFullyDefined();
3890   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3891     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3892   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3893   if(candidates->empty())
3894     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3895   std::vector<int> nodes;
3896   DataArrayInt *cellIds1D=0;
3897   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3898   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3899   MCAuto<DataArrayInt> desc1=DataArrayInt::New();
3900   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New();
3901   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New();
3902   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New();
3903   MCAuto<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3904   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3905   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3906   //
3907   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3908   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3909     cut3DCurve[*it]=-1;
3910   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3911   int ncellsSub=subMesh->getNumberOfCells();
3912   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3913   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3914                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3915                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3916   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3917   conn->alloc(0,1);
3918   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3919   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3920   for(int i=0;i<ncellsSub;i++)
3921     {
3922       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3923         {
3924           if(cut3DSurf[i].first!=-2)
3925             {
3926               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3927               connI->pushBackSilent(conn->getNumberOfTuples());
3928               cellIds2->pushBackSilent(i);
3929             }
3930           else
3931             {
3932               int cellId3DSurf=cut3DSurf[i].second;
3933               int offset=nodalI[cellId3DSurf]+1;
3934               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3935               for(int j=0;j<nbOfEdges;j++)
3936                 {
3937                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3938                   connI->pushBackSilent(conn->getNumberOfTuples());
3939                   cellIds2->pushBackSilent(cellId3DSurf);
3940                 }
3941             }
3942         }
3943     }
3944   if(cellIds2->empty())
3945     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3946   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3947   ret->setCoords(mDesc1->getCoords());
3948   ret->setConnectivity(conn,connI,true);
3949   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3950   return ret.retn();
3951 }
3952
3953 /*!
3954  * Finds cells whose bounding boxes intersect a given plane.
3955  *  \param [in] origin - 3 components of a point defining location of the plane.
3956  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3957  *         must be greater than 1e-6.
3958  *  \param [in] eps - half-thickness of the plane.
3959  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3960  *         cells. The caller is to delete this array using decrRef() as it is no more
3961  *         needed.
3962  *  \throw If the coordinates array is not set.
3963  *  \throw If the nodal connectivity of cells is not defined.
3964  *  \throw If \a this->getSpaceDimension() != 3.
3965  *  \throw If magnitude of \a vec is less than 1e-6.
3966  *  \sa buildSlice3D()
3967  */
3968 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3969 {
3970   checkFullyDefined();
3971   if(getSpaceDimension()!=3)
3972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3973   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3974   if(normm<1e-6)
3975     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3976   double vec2[3];
3977   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3978   double angle=acos(vec[2]/normm);
3979   MCAuto<DataArrayInt> cellIds;
3980   double bbox[6];
3981   if(angle>eps)
3982     {
3983       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
3984       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3985       if(normm2/normm>1e-6)
3986         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3987       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3988       mw->setCoords(coo);
3989       mw->getBoundingBox(bbox);
3990       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3991       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3992     }
3993   else
3994     {
3995       getBoundingBox(bbox);
3996       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3997       cellIds=getCellsInBoundingBox(bbox,eps);
3998     }
3999   return cellIds.retn();
4000 }
4001
4002 /*!
4003  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
4004  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
4005  * No consideration of coordinate is done by this method.
4006  * 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)
4007  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull.
4008  */
4009 bool MEDCouplingUMesh::isContiguous1D() const
4010 {
4011   if(getMeshDimension()!=1)
4012     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
4013   int nbCells=getNumberOfCells();
4014   if(nbCells<1)
4015     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
4016   const int *connI=_nodal_connec_index->getConstPointer();
4017   const int *conn=_nodal_connec->getConstPointer();
4018   int ref=conn[connI[0]+2];
4019   for(int i=1;i<nbCells;i++)
4020     {
4021       if(conn[connI[i]+1]!=ref)
4022         return false;
4023       ref=conn[connI[i]+2];
4024     }
4025   return true;
4026 }
4027
4028 /*!
4029  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4030  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4031  * \param pt reference point of the line
4032  * \param v normalized director vector of the line
4033  * \param eps max precision before throwing an exception
4034  * \param res output of size this->getNumberOfCells
4035  */
4036 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4037 {
4038   if(getMeshDimension()!=1)
4039     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4040   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4041     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4042   if(getSpaceDimension()!=3)
4043     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4044   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4045   const double *fPtr=f->getArray()->getConstPointer();
4046   double tmp[3];
4047   for(int i=0;i<getNumberOfCells();i++)
4048     {
4049       const double *tmp1=fPtr+3*i;
4050       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4051       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4052       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4053       double n1=INTERP_KERNEL::norm<3>(tmp);
4054       n1/=INTERP_KERNEL::norm<3>(tmp1);
4055       if(n1>eps)
4056         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4057     }
4058   const double *coo=getCoords()->getConstPointer();
4059   for(int i=0;i<getNumberOfNodes();i++)
4060     {
4061       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4062       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4063       res[i]=std::accumulate(tmp,tmp+3,0.);
4064     }
4065 }
4066
4067 /*!
4068  * 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. 
4069  * \a this is expected to be a mesh so that its space dimension is equal to its
4070  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4071  * 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).
4072  *
4073  * 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
4074  * 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).
4075  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4076  *
4077  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4078  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4079  *
4080  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4081  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4082  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4083  * \return the positive value of the distance.
4084  * \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
4085  * dimension - 1.
4086  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4087  */
4088 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4089 {
4090   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4091   if(meshDim!=spaceDim-1)
4092     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4093   if(meshDim!=2 && meshDim!=1)
4094     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4095   checkFullyDefined();
4096   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4097     { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
4098   DataArrayInt *ret1=0;
4099   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4100   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4101   MCAuto<DataArrayInt> ret1Safe(ret1);
4102   cellId=*ret1Safe->begin();
4103   return *ret0->begin();
4104 }
4105
4106 /*!
4107  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4108  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4109  * 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
4110  * 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).
4111  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4112  * 
4113  * \a this is expected to be a mesh so that its space dimension is equal to its
4114  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4115  * 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).
4116  *
4117  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4118  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4119  *
4120  * \param [in] pts the list of points in which each tuple represents a point
4121  * \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.
4122  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4123  * \throw if number of components of \a pts is not equal to the space dimension.
4124  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4125  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4126  */
4127 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4128 {
4129   if(!pts)
4130     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4131   pts->checkAllocated();
4132   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4133   if(meshDim!=spaceDim-1)
4134     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4135   if(meshDim!=2 && meshDim!=1)
4136     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4137   if(pts->getNumberOfComponents()!=spaceDim)
4138     {
4139       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4140       throw INTERP_KERNEL::Exception(oss.str().c_str());
4141     }
4142   checkFullyDefined();
4143   int nbCells=getNumberOfCells();
4144   if(nbCells==0)
4145     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4146   int nbOfPts=pts->getNumberOfTuples();
4147   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4148   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4149   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4150   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4151   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4152   const double *bbox(bboxArr->begin());
4153   switch(spaceDim)
4154   {
4155     case 3:
4156       {
4157         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4158         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4159           {
4160             double x=std::numeric_limits<double>::max();
4161             std::vector<int> elems;
4162             myTree.getMinDistanceOfMax(ptsPtr,x);
4163             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4164             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4165           }
4166         break;
4167       }
4168     case 2:
4169       {
4170         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4171         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4172           {
4173             double x=std::numeric_limits<double>::max();
4174             std::vector<int> elems;
4175             myTree.getMinDistanceOfMax(ptsPtr,x);
4176             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4177             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4178           }
4179         break;
4180       }
4181     default:
4182       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4183   }
4184   cellIds=ret1.retn();
4185   return ret0.retn();
4186 }
4187
4188 /// @cond INTERNAL
4189
4190 /*!
4191  * \param [in] pt the start pointer (included) of the coordinates of the point
4192  * \param [in] cellIdsBg the start pointer (included) of cellIds
4193  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4194  * \param [in] nc nodal connectivity
4195  * \param [in] ncI nodal connectivity index
4196  * \param [in,out] ret0 the min distance between \a this and the external input point
4197  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4198  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4199  */
4200 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)
4201 {
4202   cellId=-1;
4203   ret0=std::numeric_limits<double>::max();
4204   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4205     {
4206       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4207       {
4208         case INTERP_KERNEL::NORM_TRI3:
4209           {
4210             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4211             if(tmp<ret0)
4212               { ret0=tmp; cellId=*zeCell; }
4213             break;
4214           }
4215         case INTERP_KERNEL::NORM_QUAD4:
4216         case INTERP_KERNEL::NORM_POLYGON:
4217           {
4218             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4219             if(tmp<ret0)
4220               { ret0=tmp; cellId=*zeCell; }
4221             break;
4222           }
4223         default:
4224           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4225       }
4226     }
4227 }
4228
4229 /*!
4230  * \param [in] pt the start pointer (included) of the coordinates of the point
4231  * \param [in] cellIdsBg the start pointer (included) of cellIds
4232  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4233  * \param [in] nc nodal connectivity
4234  * \param [in] ncI nodal connectivity index
4235  * \param [in,out] ret0 the min distance between \a this and the external input point
4236  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4237  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4238  */
4239 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)
4240 {
4241   cellId=-1;
4242   ret0=std::numeric_limits<double>::max();
4243   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4244     {
4245       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4246       {
4247         case INTERP_KERNEL::NORM_SEG2:
4248           {
4249             std::size_t uselessEntry=0;
4250             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4251             tmp=sqrt(tmp);
4252             if(tmp<ret0)
4253               { ret0=tmp; cellId=*zeCell; }
4254             break;
4255           }
4256         default:
4257           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4258       }
4259     }
4260 }
4261 /// @endcond
4262
4263 /*!
4264  * Finds cells in contact with a ball (i.e. a point with precision). 
4265  * 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.
4266  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4267  *
4268  * \warning This method is suitable if the caller intends to evaluate only one
4269  *          point, for more points getCellsContainingPoints() is recommended as it is
4270  *          faster. 
4271  *  \param [in] pos - array of coordinates of the ball central point.
4272  *  \param [in] eps - ball radius.
4273  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4274  *         if there are no such cells.
4275  *  \throw If the coordinates array is not set.
4276  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4277  */
4278 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4279 {
4280   std::vector<int> elts;
4281   getCellsContainingPoint(pos,eps,elts);
4282   if(elts.empty())
4283     return -1;
4284   return elts.front();
4285 }
4286
4287 /*!
4288  * Finds cells in contact with a ball (i.e. a point with precision).
4289  * 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.
4290  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4291  * \warning This method is suitable if the caller intends to evaluate only one
4292  *          point, for more points getCellsContainingPoints() is recommended as it is
4293  *          faster. 
4294  *  \param [in] pos - array of coordinates of the ball central point.
4295  *  \param [in] eps - ball radius.
4296  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4297  *         before inserting ids.
4298  *  \throw If the coordinates array is not set.
4299  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4300  *
4301  *  \if ENABLE_EXAMPLES
4302  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4303  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4304  *  \endif
4305  */
4306 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4307 {
4308   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4309   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4310   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4311 }
4312
4313 /// @cond INTERNAL
4314
4315 namespace MEDCoupling
4316 {
4317   template<const int SPACEDIMM>
4318   class DummyClsMCUG
4319   {
4320   public:
4321     static const int MY_SPACEDIM=SPACEDIMM;
4322     static const int MY_MESHDIM=8;
4323     typedef int MyConnType;
4324     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4325     // begin
4326     // useless, but for windows compilation ...
4327     const double* getCoordinatesPtr() const { return 0; }
4328     const int* getConnectivityPtr() const { return 0; }
4329     const int* getConnectivityIndexPtr() const { return 0; }
4330     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4331     // end
4332   };
4333
4334   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MCAuto<INTERP_KERNEL::Node>,int>& m)
4335   {
4336     INTERP_KERNEL::Edge *ret(0);
4337     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]));
4338     m[n0]=bg[0]; m[n1]=bg[1];
4339     switch(typ)
4340     {
4341       case INTERP_KERNEL::NORM_SEG2:
4342         {
4343           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4344           break;
4345         }
4346       case INTERP_KERNEL::NORM_SEG3:
4347         {
4348           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4349           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4350           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4351           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4352           bool colinearity(inters.areColinears());
4353           delete e1; delete e2;
4354           if(colinearity)
4355             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4356           else
4357             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4358           break;
4359         }
4360       default:
4361         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4362     }
4363     return ret;
4364   }
4365
4366   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4367   {
4368     INTERP_KERNEL::Edge *ret=0;
4369     switch(typ)
4370     {
4371       case INTERP_KERNEL::NORM_SEG2:
4372         {
4373           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4374           break;
4375         }
4376       case INTERP_KERNEL::NORM_SEG3:
4377         {
4378           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4379           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4380           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4381           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4382           bool colinearity=inters.areColinears();
4383           delete e1; delete e2;
4384           if(colinearity)
4385             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4386           else
4387             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4388           mapp2[bg[2]].second=false;
4389           break;
4390         }
4391       default:
4392         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4393     }
4394     return ret;
4395   }
4396
4397   /*!
4398    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4399    * the global mesh 'mDesc'.
4400    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4401    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4402    */
4403   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4404                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4405   {
4406     mapp.clear();
4407     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.
4408     const double *coo=mDesc->getCoords()->getConstPointer();
4409     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4410     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4411     std::set<int> s;
4412     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4413       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4414     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4415       {
4416         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4417         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4418       }
4419     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4420     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4421       {
4422         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4423         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4424       }
4425     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4426       {
4427         if((*it2).second.second)
4428           mapp[(*it2).second.first]=(*it2).first;
4429         ((*it2).second.first)->decrRef();
4430       }
4431     return ret;
4432   }
4433
4434   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4435   {
4436     if(nodeId>=offset2)
4437       {
4438         int locId=nodeId-offset2;
4439         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4440       }
4441     if(nodeId>=offset1)
4442       {
4443         int locId=nodeId-offset1;
4444         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4445       }
4446     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4447   }
4448
4449   /**
4450    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4451    */
4452   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4453                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4454                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4455   {
4456     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4457       {
4458         int eltId1=abs(*desc1)-1;
4459         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4460           {
4461             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4462             if(it==mappRev.end())
4463               {
4464                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4465                 mapp[node]=*it1;
4466                 mappRev[*it1]=node;
4467               }
4468           }
4469       }
4470   }
4471 }
4472
4473 /// @endcond
4474
4475 template<int SPACEDIM>
4476 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4477                                                    double eps, MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4478 {
4479   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4480   int *eltsIndexPtr(eltsIndex->getPointer());
4481   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4482   const double *bbox(bboxArr->begin());
4483   int nbOfCells=getNumberOfCells();
4484   const int *conn=_nodal_connec->getConstPointer();
4485   const int *connI=_nodal_connec_index->getConstPointer();
4486   double bb[2*SPACEDIM];
4487   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4488   for(int i=0;i<nbOfPoints;i++)
4489     {
4490       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4491       for(int j=0;j<SPACEDIM;j++)
4492         {
4493           bb[2*j]=pos[SPACEDIM*i+j];
4494           bb[2*j+1]=pos[SPACEDIM*i+j];
4495         }
4496       std::vector<int> candidates;
4497       myTree.getIntersectingElems(bb,candidates);
4498       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4499         {
4500           int sz(connI[(*iter)+1]-connI[*iter]-1);
4501           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4502           bool status(false);
4503           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4504             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4505           else
4506             {
4507               if(SPACEDIM!=2)
4508                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4509               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4510               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4511               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4512               INTERP_KERNEL::QuadraticPolygon *pol(0);
4513               for(int j=0;j<sz;j++)
4514                 {
4515                   int nodeId(conn[connI[*iter]+1+j]);
4516                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4517                 }
4518               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4519                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4520               else
4521                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4522               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4523               double a(0.),b(0.),c(0.);
4524               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4525               status=pol->isInOrOut2(n);
4526               delete pol; n->decrRef();
4527             }
4528           if(status)
4529             {
4530               eltsIndexPtr[i+1]++;
4531               elts->pushBackSilent(*iter);
4532             }
4533         }
4534     }
4535 }
4536 /*!
4537  * Finds cells in contact with several balls (i.e. points with precision).
4538  * This method is an extension of getCellContainingPoint() and
4539  * getCellsContainingPoint() for the case of multiple points.
4540  * 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.
4541  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4542  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4543  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4544  *         this->getSpaceDimension() * \a nbOfPoints 
4545  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4546  *  \param [in] eps - radius of balls (i.e. the precision).
4547  *  \param [out] elts - vector returning ids of found cells.
4548  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4549  *         dividing cell ids in \a elts into groups each referring to one
4550  *         point. Its every element (except the last one) is an index pointing to the
4551  *         first id of a group of cells. For example cells in contact with the *i*-th
4552  *         point are described by following range of indices:
4553  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4554  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4555  *         Number of cells in contact with the *i*-th point is
4556  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4557  *  \throw If the coordinates array is not set.
4558  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4559  *
4560  *  \if ENABLE_EXAMPLES
4561  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4562  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4563  *  \endif
4564  */
4565 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4566                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4567 {
4568   int spaceDim=getSpaceDimension();
4569   int mDim=getMeshDimension();
4570   if(spaceDim==3)
4571     {
4572       if(mDim==3)
4573         {
4574           const double *coords=_coords->getConstPointer();
4575           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4576         }
4577       /*else if(mDim==2)
4578         {
4579
4580         }*/
4581       else
4582         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4583     }
4584   else if(spaceDim==2)
4585     {
4586       if(mDim==2)
4587         {
4588           const double *coords=_coords->getConstPointer();
4589           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4590         }
4591       else
4592         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4593     }
4594   else if(spaceDim==1)
4595     {
4596       if(mDim==1)
4597         {
4598           const double *coords=_coords->getConstPointer();
4599           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4600         }
4601       else
4602         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4603     }
4604   else
4605     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4606 }
4607
4608 /*!
4609  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4610  * least two its edges intersect each other anywhere except their extremities. An
4611  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4612  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4613  *         cleared before filling in.
4614  *  \param [in] eps - precision.
4615  *  \throw If \a this->getMeshDimension() != 2.
4616  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4617  */
4618 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4619 {
4620   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4621   if(getMeshDimension()!=2)
4622     throw INTERP_KERNEL::Exception(msg);
4623   int spaceDim=getSpaceDimension();
4624   if(spaceDim!=2 && spaceDim!=3)
4625     throw INTERP_KERNEL::Exception(msg);
4626   const int *conn=_nodal_connec->getConstPointer();
4627   const int *connI=_nodal_connec_index->getConstPointer();
4628   int nbOfCells=getNumberOfCells();
4629   std::vector<double> cell2DinS2;
4630   for(int i=0;i<nbOfCells;i++)
4631     {
4632       int offset=connI[i];
4633       int nbOfNodesForCell=connI[i+1]-offset-1;
4634       if(nbOfNodesForCell<=3)
4635         continue;
4636       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4637       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4638       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4639         cells.push_back(i);
4640       cell2DinS2.clear();
4641     }
4642 }
4643
4644 /*!
4645  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4646  *
4647  * 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.
4648  * 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.
4649  * 
4650  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4651  * This convex envelop is computed using Jarvis march algorithm.
4652  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4653  * 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)
4654  * 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.
4655  *
4656  * \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.
4657  * \sa MEDCouplingUMesh::colinearize2D
4658  */
4659 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4660 {
4661   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4662     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4663   checkFullyDefined();
4664   const double *coords=getCoords()->getConstPointer();
4665   int nbOfCells=getNumberOfCells();
4666   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4667   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4668   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4669   int *workIndexOut=nodalConnecIndexOut->getPointer();
4670   *workIndexOut=0;
4671   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4672   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4673   std::set<INTERP_KERNEL::NormalizedCellType> types;
4674   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4675   isChanged->alloc(0,1);
4676   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4677     {
4678       int pos=nodalConnecOut->getNumberOfTuples();
4679       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4680         isChanged->pushBackSilent(i);
4681       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4682       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4683     }
4684   if(isChanged->empty())
4685     return 0;
4686   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4687   _types=types;
4688   return isChanged.retn();
4689 }
4690
4691 /*!
4692  * This method is \b NOT const because it can modify \a this.
4693  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4694  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4695  * \param policy specifies the type of extrusion chosen:
4696  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4697  *   will be repeated to build each level
4698  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4699  *   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
4700  *   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
4701  *   arc.
4702  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4703  */
4704 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4705 {
4706   checkFullyDefined();
4707   mesh1D->checkFullyDefined();
4708   if(!mesh1D->isContiguous1D())
4709     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4710   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4711     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4712   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4713     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4714   if(mesh1D->getMeshDimension()!=1)
4715     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4716   bool isQuad=false;
4717   if(isPresenceOfQuadratic())
4718     {
4719       if(mesh1D->isFullyQuadratic())
4720         isQuad=true;
4721       else
4722         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4723     }
4724   int oldNbOfNodes(getNumberOfNodes());
4725   MCAuto<DataArrayDouble> newCoords;
4726   switch(policy)
4727   {
4728     case 0:
4729       {
4730         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4731         break;
4732       }
4733     case 1:
4734       {
4735         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4736         break;
4737       }
4738     default:
4739       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4740   }
4741   setCoords(newCoords);
4742   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4743   updateTime();
4744   return ret.retn();
4745 }
4746
4747 /*!
4748  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4749  * If it is not the case an exception will be thrown.
4750  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4751  * intersection of plane defined by ('origin','vec').
4752  * This method has one in/out parameter : 'cut3DCurve'.
4753  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4754  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4755  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4756  * This method will throw an exception if \a this contains a non linear segment.
4757  */
4758 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4759 {
4760   checkFullyDefined();
4761   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4762     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4763   int ncells=getNumberOfCells();
4764   int nnodes=getNumberOfNodes();
4765   double vec2[3],vec3[3],vec4[3];
4766   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4767   if(normm<1e-6)
4768     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4769   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4770   const int *conn=_nodal_connec->getConstPointer();
4771   const int *connI=_nodal_connec_index->getConstPointer();
4772   const double *coo=_coords->getConstPointer();
4773   std::vector<double> addCoo;
4774   for(int i=0;i<ncells;i++)
4775     {
4776       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4777         {
4778           if(cut3DCurve[i]==-2)
4779             {
4780               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4781               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];
4782               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4783               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4784               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4785                 {
4786                   const double *st2=coo+3*st;
4787                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4788                   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]));
4789                   if(pos>eps && pos<1-eps)
4790                     {
4791                       int nNode=((int)addCoo.size())/3;
4792                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4793                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4794                       cut3DCurve[i]=nnodes+nNode;
4795                     }
4796                 }
4797             }
4798         }
4799       else
4800         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4801     }
4802   if(!addCoo.empty())
4803     {
4804       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4805       MCAuto<DataArrayDouble> coo2=DataArrayDouble::New();
4806       coo2->alloc(newNbOfNodes,3);
4807       double *tmp=coo2->getPointer();
4808       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4809       std::copy(addCoo.begin(),addCoo.end(),tmp);
4810       DataArrayDouble::SetArrayIn(coo2,_coords);
4811     }
4812 }
4813
4814 /*!
4815  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4816  * \param mesh1D is the input 1D mesh used for translation computation.
4817  * \return newCoords new coords filled by this method. 
4818  */
4819 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4820 {
4821   int oldNbOfNodes=getNumberOfNodes();
4822   int nbOf1DCells=mesh1D->getNumberOfCells();
4823   int spaceDim=getSpaceDimension();
4824   DataArrayDouble *ret=DataArrayDouble::New();
4825   std::vector<bool> isQuads;
4826   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4827   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4828   double *retPtr=ret->getPointer();
4829   const double *coords=getCoords()->getConstPointer();
4830   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4831   std::vector<int> v;
4832   std::vector<double> c;
4833   double vec[3];
4834   v.reserve(3);
4835   c.reserve(6);
4836   for(int i=0;i<nbOf1DCells;i++)
4837     {
4838       v.resize(0);
4839       mesh1D->getNodeIdsOfCell(i,v);
4840       c.resize(0);
4841       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4842       mesh1D->getCoordinatesOfNode(v[0],c);
4843       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4844       for(int j=0;j<oldNbOfNodes;j++)
4845         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4846       if(isQuad)
4847         {
4848           c.resize(0);
4849           mesh1D->getCoordinatesOfNode(v[1],c);
4850           mesh1D->getCoordinatesOfNode(v[0],c);
4851           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4852           for(int j=0;j<oldNbOfNodes;j++)
4853             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4854         }
4855     }
4856   ret->copyStringInfoFrom(*getCoords());
4857   return ret;
4858 }
4859
4860 /*!
4861  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4862  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4863  * \return newCoords new coords filled by this method. 
4864  */
4865 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4866 {
4867   if(mesh1D->getSpaceDimension()==2)
4868     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4869   if(mesh1D->getSpaceDimension()==3)
4870     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4871   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4872 }
4873
4874 /*!
4875  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4876  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4877  * \return newCoords new coords filled by this method. 
4878  */
4879 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4880 {
4881   if(isQuad)
4882     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4883   int oldNbOfNodes=getNumberOfNodes();
4884   int nbOf1DCells=mesh1D->getNumberOfCells();
4885   if(nbOf1DCells<2)
4886     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4887   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
4888   int nbOfLevsInVec=nbOf1DCells+1;
4889   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4890   double *retPtr=ret->getPointer();
4891   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4892   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4893   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
4894   tmp->setCoords(tmp2);
4895   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4896   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4897   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4898   for(int i=1;i<nbOfLevsInVec;i++)
4899     {
4900       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4901       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4902       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4903       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4904       tmp->translate(vec);
4905       double tmp3[2],radius,alpha,alpha0;
4906       const double *p0=i+1<nbOfLevsInVec?begin:third;
4907       const double *p1=i+1<nbOfLevsInVec?end:begin;
4908       const double *p2=i+1<nbOfLevsInVec?third:end;
4909       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4910       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]);
4911       double angle=acos(cosangle/(radius*radius));
4912       tmp->rotate(end,0,angle);
4913       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4914     }
4915   return ret.retn();
4916 }
4917
4918 /*!
4919  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4920  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4921  * \return newCoords new coords filled by this method. 
4922  */
4923 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4924 {
4925   if(isQuad)
4926     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4927   int oldNbOfNodes=getNumberOfNodes();
4928   int nbOf1DCells=mesh1D->getNumberOfCells();
4929   if(nbOf1DCells<2)
4930     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4931   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
4932   int nbOfLevsInVec=nbOf1DCells+1;
4933   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4934   double *retPtr=ret->getPointer();
4935   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4936   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4937   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
4938   tmp->setCoords(tmp2);
4939   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4940   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4941   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4942   for(int i=1;i<nbOfLevsInVec;i++)
4943     {
4944       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4945       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4946       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4947       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4948       tmp->translate(vec);
4949       double tmp3[2],radius,alpha,alpha0;
4950       const double *p0=i+1<nbOfLevsInVec?begin:third;
4951       const double *p1=i+1<nbOfLevsInVec?end:begin;
4952       const double *p2=i+1<nbOfLevsInVec?third:end;
4953       double vecPlane[3]={
4954         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4955         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4956         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4957       };
4958       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4959       if(norm>1.e-7)
4960         {
4961           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4962           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4963           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4964           double s2=norm2;
4965           double c2=cos(asin(s2));
4966           double m[3][3]={
4967             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4968             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4969             {-vec2[1]*s2, vec2[0]*s2, c2}
4970           };
4971           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]};
4972           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]};
4973           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]};
4974           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4975           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]);
4976           double angle=acos(cosangle/(radius*radius));
4977           tmp->rotate(end,vecPlane,angle);
4978         }
4979       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4980     }
4981   return ret.retn();
4982 }
4983
4984 /*!
4985  * This method is private because not easy to use for end user. This method is const contrary to
4986  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4987  * the coords sorted slice by slice.
4988  * \param isQuad specifies presence of quadratic cells.
4989  */
4990 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4991 {
4992   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4993   int nbOf2DCells(getNumberOfCells());
4994   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4995   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4996   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4997   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4998   newConnI->alloc(nbOf3DCells+1,1);
4999   int *newConnIPtr(newConnI->getPointer());
5000   *newConnIPtr++=0;
5001   std::vector<int> newc;
5002   for(int j=0;j<nbOf2DCells;j++)
5003     {
5004       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
5005       *newConnIPtr++=(int)newc.size();
5006     }
5007   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
5008   int *newConnPtr(newConn->getPointer());
5009   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
5010   newConnIPtr=newConnI->getPointer();
5011   for(int iz=0;iz<nbOf1DCells;iz++)
5012     {
5013       if(iz!=0)
5014         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
5015       const int *posOfTypeOfCell(newConnIPtr);
5016       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
5017         {
5018           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
5019           if(icell!=*posOfTypeOfCell)
5020             {
5021               if(*iter!=-1)
5022                 *newConnPtr=(*iter)+iz*deltaPerLev;
5023               else
5024                 *newConnPtr=-1;
5025             }
5026           else
5027             {
5028               *newConnPtr=*iter;
5029               posOfTypeOfCell++;
5030             }
5031         }
5032     }
5033   ret->setConnectivity(newConn,newConnI,true);
5034   ret->setCoords(getCoords());
5035   return ret;
5036 }
5037
5038 /*!
5039  * Checks if \a this mesh is constituted by only quadratic cells.
5040  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
5041  *  \throw If the coordinates array is not set.
5042  *  \throw If the nodal connectivity of cells is not defined.
5043  */
5044 bool MEDCouplingUMesh::isFullyQuadratic() const
5045 {
5046   checkFullyDefined();
5047   bool ret=true;
5048   int nbOfCells=getNumberOfCells();
5049   for(int i=0;i<nbOfCells && ret;i++)
5050     {
5051       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5052       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5053       ret=cm.isQuadratic();
5054     }
5055   return ret;
5056 }
5057
5058 /*!
5059  * Checks if \a this mesh includes any quadratic cell.
5060  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5061  *  \throw If the coordinates array is not set.
5062  *  \throw If the nodal connectivity of cells is not defined.
5063  */
5064 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5065 {
5066   checkFullyDefined();
5067   bool ret=false;
5068   int nbOfCells=getNumberOfCells();
5069   for(int i=0;i<nbOfCells && !ret;i++)
5070     {
5071       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5072       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5073       ret=cm.isQuadratic();
5074     }
5075   return ret;
5076 }
5077
5078 /*!
5079  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5080  * this mesh, it remains unchanged.
5081  *  \throw If the coordinates array is not set.
5082  *  \throw If the nodal connectivity of cells is not defined.
5083  */
5084 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5085 {
5086   checkFullyDefined();
5087   int nbOfCells=getNumberOfCells();
5088   int delta=0;
5089   const int *iciptr=_nodal_connec_index->getConstPointer();
5090   for(int i=0;i<nbOfCells;i++)
5091     {
5092       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5093       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5094       if(cm.isQuadratic())
5095         {
5096           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5097           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5098           if(!cml.isDynamic())
5099             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5100           else
5101             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5102         }
5103     }
5104   if(delta==0)
5105     return ;
5106   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5107   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5108   const int *icptr=_nodal_connec->getConstPointer();
5109   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
5110   newConnI->alloc(nbOfCells+1,1);
5111   int *ocptr=newConn->getPointer();
5112   int *ociptr=newConnI->getPointer();
5113   *ociptr=0;
5114   _types.clear();
5115   for(int i=0;i<nbOfCells;i++,ociptr++)
5116     {
5117       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5118       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5119       if(!cm.isQuadratic())
5120         {
5121           _types.insert(type);
5122           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5123           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5124         }
5125       else
5126         {
5127           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5128           _types.insert(typel);
5129           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5130           int newNbOfNodes=cml.getNumberOfNodes();
5131           if(cml.isDynamic())
5132             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5133           *ocptr++=(int)typel;
5134           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5135           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5136         }
5137     }
5138   setConnectivity(newConn,newConnI,false);
5139 }
5140
5141 /*!
5142  * This method converts all linear cell in \a this to quadratic one.
5143  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5144  * 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)
5145  * 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.
5146  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5147  * end of the existing coordinates.
5148  * 
5149  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5150  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5151  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5152  * 
5153  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5154  *
5155  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5156  */
5157 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5158 {
5159   DataArrayInt *conn=0,*connI=0;
5160   DataArrayDouble *coords=0;
5161   std::set<INTERP_KERNEL::NormalizedCellType> types;
5162   checkFullyDefined();
5163   MCAuto<DataArrayInt> ret,connSafe,connISafe;
5164   MCAuto<DataArrayDouble> coordsSafe;
5165   int meshDim=getMeshDimension();
5166   switch(conversionType)
5167   {
5168     case 0:
5169       switch(meshDim)
5170       {
5171         case 1:
5172           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5173           connSafe=conn; connISafe=connI; coordsSafe=coords;
5174           break;
5175         case 2:
5176           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5177           connSafe=conn; connISafe=connI; coordsSafe=coords;
5178           break;
5179         case 3:
5180           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5181           connSafe=conn; connISafe=connI; coordsSafe=coords;
5182           break;
5183         default:
5184           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5185       }
5186       break;
5187         case 1:
5188           {
5189             switch(meshDim)
5190             {
5191               case 1:
5192                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5193                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5194                 break;
5195               case 2:
5196                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5197                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5198                 break;
5199               case 3:
5200                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5201                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5202                 break;
5203               default:
5204                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5205             }
5206             break;
5207           }
5208         default:
5209           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5210   }
5211   setConnectivity(connSafe,connISafe,false);
5212   _types=types;
5213   setCoords(coordsSafe);
5214   return ret.retn();
5215 }
5216
5217 /*!
5218  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5219  * so that the number of cells remains the same. Quadratic faces are converted to
5220  * polygons. This method works only for 2D meshes in
5221  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5222  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5223  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5224  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5225  *         a polylinized edge constituting the input polygon.
5226  *  \throw If the coordinates array is not set.
5227  *  \throw If the nodal connectivity of cells is not defined.
5228  *  \throw If \a this->getMeshDimension() != 2.
5229  *  \throw If \a this->getSpaceDimension() != 2.
5230  */
5231 void MEDCouplingUMesh::tessellate2D(double eps)
5232 {
5233   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
5234   if(spaceDim!=2)
5235     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
5236   switch(meshDim)
5237     {
5238     case 1:
5239       return tessellate2DCurveInternal(eps);
5240     case 2:
5241       return tessellate2DInternal(eps);
5242     default:
5243       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
5244     }
5245 }
5246 /*!
5247  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5248  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5249  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5250  *         a sub-divided edge.
5251  *  \throw If the coordinates array is not set.
5252  *  \throw If the nodal connectivity of cells is not defined.
5253  *  \throw If \a this->getMeshDimension() != 1.
5254  *  \throw If \a this->getSpaceDimension() != 2.
5255  */
5256
5257 #if 0
5258 /*!
5259  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5260  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5261  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5262  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5263  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5264  * This method can be seen as the opposite method of colinearize2D.
5265  * 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
5266  * to avoid to modify the numbering of existing nodes.
5267  *
5268  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5269  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5270  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5271  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5272  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5273  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5274  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5275  *
5276  * \sa buildDescendingConnectivity2
5277  */
5278 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5279                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5280 {
5281   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5282     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5283   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5284   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5285     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5286   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5287     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5288   //DataArrayInt *out0(0),*outi0(0);
5289   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5290   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
5291   //out0s=out0s->buildUnique(); out0s->sort(true);
5292 }
5293 #endif
5294
5295 /*!
5296  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5297  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5298  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5299  */
5300 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5301 {
5302   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5303   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5304   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5305   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5306   int nbOfCells=getNumberOfCells();
5307   int nbOfNodes=getNumberOfNodes();
5308   const int *cPtr=_nodal_connec->getConstPointer();
5309   const int *icPtr=_nodal_connec_index->getConstPointer();
5310   int lastVal=0,offset=nbOfNodes;
5311   for(int i=0;i<nbOfCells;i++,icPtr++)
5312     {
5313       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5314       if(type==INTERP_KERNEL::NORM_SEG2)
5315         {
5316           types.insert(INTERP_KERNEL::NORM_SEG3);
5317           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5318           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5319           newConn->pushBackSilent(offset++);
5320           lastVal+=4;
5321           newConnI->pushBackSilent(lastVal);
5322           ret->pushBackSilent(i);
5323         }
5324       else
5325         {
5326           types.insert(type);
5327           lastVal+=(icPtr[1]-icPtr[0]);
5328           newConnI->pushBackSilent(lastVal);
5329           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5330         }
5331     }
5332   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5333   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5334   return ret.retn();
5335 }
5336
5337 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
5338 {
5339   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5340   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5341   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5342   //
5343   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5344   DataArrayInt *conn1D=0,*conn1DI=0;
5345   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5346   DataArrayDouble *coordsTmp=0;
5347   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5348   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5349   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5350   const int *c1DPtr=conn1D->begin();
5351   const int *c1DIPtr=conn1DI->begin();
5352   int nbOfCells=getNumberOfCells();
5353   const int *cPtr=_nodal_connec->getConstPointer();
5354   const int *icPtr=_nodal_connec_index->getConstPointer();
5355   int lastVal=0;
5356   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5357     {
5358       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5359       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5360       if(!cm.isQuadratic())
5361         {
5362           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5363           types.insert(typ2); newConn->pushBackSilent(typ2);
5364           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5365           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5366             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5367           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5368           newConnI->pushBackSilent(lastVal);
5369           ret->pushBackSilent(i);
5370         }
5371       else
5372         {
5373           types.insert(typ);
5374           lastVal+=(icPtr[1]-icPtr[0]);
5375           newConnI->pushBackSilent(lastVal);
5376           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5377         }
5378     }
5379   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5380   return ret.retn();
5381 }
5382
5383 /*!
5384  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5385  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5386  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5387  */
5388 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5389 {
5390   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5391   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5392   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5393 }
5394
5395 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5396 {
5397   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5398   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5399   //
5400   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5401   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5402   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5403   //
5404   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5405   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5406   DataArrayInt *conn1D=0,*conn1DI=0;
5407   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5408   DataArrayDouble *coordsTmp=0;
5409   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5410   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5411   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5412   const int *c1DPtr=conn1D->begin();
5413   const int *c1DIPtr=conn1DI->begin();
5414   int nbOfCells=getNumberOfCells();
5415   const int *cPtr=_nodal_connec->getConstPointer();
5416   const int *icPtr=_nodal_connec_index->getConstPointer();
5417   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5418   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5419     {
5420       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5421       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5422       if(!cm.isQuadratic())
5423         {
5424           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5425           types.insert(typ2); newConn->pushBackSilent(typ2);
5426           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5427           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5428             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5429           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5430           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5431           newConnI->pushBackSilent(lastVal);
5432           ret->pushBackSilent(i);
5433         }
5434       else
5435         {
5436           types.insert(typ);
5437           lastVal+=(icPtr[1]-icPtr[0]);
5438           newConnI->pushBackSilent(lastVal);
5439           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5440         }
5441     }
5442   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5443   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5444   return ret.retn();
5445 }
5446
5447 /*!
5448  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5449  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5450  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5451  */
5452 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5453 {
5454   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5455   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5456   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5457 }
5458
5459 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5460 {
5461   MCAuto<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5462   MCAuto<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5463   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5464   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5465   //
5466   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5467   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5468   MCAuto<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5469   //
5470   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5471   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5472   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5473   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5474   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5475   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5476   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5477   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5478   MCAuto<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5479   MCAuto<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5480   MCAuto<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5481   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5482   int nbOfCells=getNumberOfCells();
5483   const int *cPtr=_nodal_connec->getConstPointer();
5484   const int *icPtr=_nodal_connec_index->getConstPointer();
5485   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5486   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5487     {
5488       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5489       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5490       if(!cm.isQuadratic())
5491         {
5492           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5493           if(typ2==INTERP_KERNEL::NORM_ERROR)
5494             {
5495               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5496               throw INTERP_KERNEL::Exception(oss.str().c_str());
5497             }
5498           types.insert(typ2); newConn->pushBackSilent(typ2);
5499           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5500           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5501             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5502           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5503             {
5504               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5505               int tmpPos=newConn->getNumberOfTuples();
5506               newConn->pushBackSilent(nodeId2);
5507               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5508             }
5509           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5510           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5511           newConnI->pushBackSilent(lastVal);
5512           ret->pushBackSilent(i);
5513         }
5514       else
5515         {
5516           types.insert(typ);
5517           lastVal+=(icPtr[1]-icPtr[0]);
5518           newConnI->pushBackSilent(lastVal);
5519           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5520         }
5521     }
5522   MCAuto<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5523   MCAuto<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5524   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5525   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5526   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5527   int *c=newConn->getPointer();
5528   const int *cI(newConnI->begin());
5529   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5530     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5531   offset=coordsTmp2Safe->getNumberOfTuples();
5532   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5533     c[cI[(*elt)+1]-1]+=offset;
5534   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5535   return ret.retn();
5536 }
5537
5538 /*!
5539  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5540  * In addition, returns an array mapping new cells to old ones. <br>
5541  * This method typically increases the number of cells in \a this mesh
5542  * but the number of nodes remains \b unchanged.
5543  * That's why the 3D splitting policies
5544  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5545  *  \param [in] policy - specifies a pattern used for splitting.
5546  * The semantic of \a policy is:
5547  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5548  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5549  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5550  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5551  *
5552  *
5553  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5554  *          an id of old cell producing it. The caller is to delete this array using
5555  *         decrRef() as it is no more needed.
5556  *
5557  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5558  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5559  *          and \a this->getMeshDimension() != 3. 
5560  *  \throw If \a policy is not one of the four discussed above.
5561  *  \throw If the nodal connectivity of cells is not defined.
5562  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5563  */
5564 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5565 {
5566   switch(policy)
5567   {
5568     case 0:
5569       return simplexizePol0();
5570     case 1:
5571       return simplexizePol1();
5572     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5573         return simplexizePlanarFace5();
5574     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5575         return simplexizePlanarFace6();
5576     default:
5577       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)");
5578   }
5579 }
5580
5581 /*!
5582  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5583  * - 1D: INTERP_KERNEL::NORM_SEG2
5584  * - 2D: INTERP_KERNEL::NORM_TRI3
5585  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5586  *
5587  * This method is useful for users that need to use P1 field services as
5588  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5589  * All these methods need mesh support containing only simplex cells.
5590  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5591  *  \throw If the coordinates array is not set.
5592  *  \throw If the nodal connectivity of cells is not defined.
5593  *  \throw If \a this->getMeshDimension() < 1.
5594  */
5595 bool MEDCouplingUMesh::areOnlySimplexCells() const
5596 {
5597   checkFullyDefined();
5598   int mdim=getMeshDimension();
5599   if(mdim<1 || mdim>3)
5600     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5601   int nbCells=getNumberOfCells();
5602   const int *conn=_nodal_connec->getConstPointer();
5603   const int *connI=_nodal_connec_index->getConstPointer();
5604   for(int i=0;i<nbCells;i++)
5605     {
5606       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5607       if(!cm.isSimplex())
5608         return false;
5609     }
5610   return true;
5611 }
5612
5613 /*!
5614  * This method implements policy 0 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5615  */
5616 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5617 {
5618   checkConnectivityFullyDefined();
5619   if(getMeshDimension()!=2)
5620     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5621   int nbOfCells=getNumberOfCells();
5622   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5623   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5624   ret->alloc(nbOfCells+nbOfCutCells,1);
5625   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5626   int *retPt=ret->getPointer();
5627   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5628   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5629   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5630   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5631   int *pt=newConn->getPointer();
5632   int *ptI=newConnI->getPointer();
5633   ptI[0]=0;
5634   const int *oldc=_nodal_connec->getConstPointer();
5635   const int *ci=_nodal_connec_index->getConstPointer();
5636   for(int i=0;i<nbOfCells;i++,ci++)
5637     {
5638       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5639         {
5640           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5641             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5642           pt=std::copy(tmp,tmp+8,pt);
5643           ptI[1]=ptI[0]+4;
5644           ptI[2]=ptI[0]+8;
5645           *retPt++=i;
5646           *retPt++=i;
5647           ptI+=2;
5648         }
5649       else
5650         {
5651           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5652           ptI[1]=ptI[0]+ci[1]-ci[0];
5653           ptI++;
5654           *retPt++=i;
5655         }
5656     }
5657   _nodal_connec->decrRef();
5658   _nodal_connec=newConn.retn();
5659   _nodal_connec_index->decrRef();
5660   _nodal_connec_index=newConnI.retn();
5661   computeTypes();
5662   updateTime();
5663   return ret.retn();
5664 }
5665
5666 /*!
5667  * This method implements policy 1 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5668  */
5669 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5670 {
5671   checkConnectivityFullyDefined();
5672   if(getMeshDimension()!=2)
5673     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5674   int nbOfCells=getNumberOfCells();
5675   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5676   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5677   ret->alloc(nbOfCells+nbOfCutCells,1);
5678   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5679   int *retPt=ret->getPointer();
5680   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5681   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5682   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5683   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5684   int *pt=newConn->getPointer();
5685   int *ptI=newConnI->getPointer();
5686   ptI[0]=0;
5687   const int *oldc=_nodal_connec->getConstPointer();
5688   const int *ci=_nodal_connec_index->getConstPointer();
5689   for(int i=0;i<nbOfCells;i++,ci++)
5690     {
5691       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5692         {
5693           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5694             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5695           pt=std::copy(tmp,tmp+8,pt);
5696           ptI[1]=ptI[0]+4;
5697           ptI[2]=ptI[0]+8;
5698           *retPt++=i;
5699           *retPt++=i;
5700           ptI+=2;
5701         }
5702       else
5703         {
5704           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5705           ptI[1]=ptI[0]+ci[1]-ci[0];
5706           ptI++;
5707           *retPt++=i;
5708         }
5709     }
5710   _nodal_connec->decrRef();
5711   _nodal_connec=newConn.retn();
5712   _nodal_connec_index->decrRef();
5713   _nodal_connec_index=newConnI.retn();
5714   computeTypes();
5715   updateTime();
5716   return ret.retn();
5717 }
5718
5719 /*!
5720  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5721  */
5722 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5723 {
5724   checkConnectivityFullyDefined();
5725   if(getMeshDimension()!=3)
5726     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5727   int nbOfCells=getNumberOfCells();
5728   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5729   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5730   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5731   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5732   int *retPt=ret->getPointer();
5733   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5734   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5735   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5736   newConn->alloc(getNodalConnectivityArrayLen()+16*nbOfCutCells,1);//21
5737   int *pt=newConn->getPointer();
5738   int *ptI=newConnI->getPointer();
5739   ptI[0]=0;
5740   const int *oldc=_nodal_connec->getConstPointer();
5741   const int *ci=_nodal_connec_index->getConstPointer();
5742   for(int i=0;i<nbOfCells;i++,ci++)
5743     {
5744       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5745         {
5746           for(int j=0;j<5;j++,pt+=5,ptI++)
5747             {
5748               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5749               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];
5750               *retPt++=i;
5751               ptI[1]=ptI[0]+5;
5752             }
5753         }
5754       else
5755         {
5756           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5757           ptI[1]=ptI[0]+ci[1]-ci[0];
5758           ptI++;
5759           *retPt++=i;
5760         }
5761     }
5762   _nodal_connec->decrRef();
5763   _nodal_connec=newConn.retn();
5764   _nodal_connec_index->decrRef();
5765   _nodal_connec_index=newConnI.retn();
5766   computeTypes();
5767   updateTime();
5768   return ret.retn();
5769 }
5770
5771 /*!
5772  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5773  */
5774 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5775 {
5776   checkConnectivityFullyDefined();
5777   if(getMeshDimension()!=3)
5778     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5779   int nbOfCells=getNumberOfCells();
5780   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5781   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5782   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5783   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5784   int *retPt=ret->getPointer();
5785   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5786   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5787   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5788   newConn->alloc(getNodalConnectivityArrayLen()+21*nbOfCutCells,1);
5789   int *pt=newConn->getPointer();
5790   int *ptI=newConnI->getPointer();
5791   ptI[0]=0;
5792   const int *oldc=_nodal_connec->getConstPointer();
5793   const int *ci=_nodal_connec_index->getConstPointer();
5794   for(int i=0;i<nbOfCells;i++,ci++)
5795     {
5796       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5797         {
5798           for(int j=0;j<6;j++,pt+=5,ptI++)
5799             {
5800               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5801               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];
5802               *retPt++=i;
5803               ptI[1]=ptI[0]+5;
5804             }
5805         }
5806       else
5807         {
5808           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5809           ptI[1]=ptI[0]+ci[1]-ci[0];
5810           ptI++;
5811           *retPt++=i;
5812         }
5813     }
5814   _nodal_connec->decrRef();
5815   _nodal_connec=newConn.retn();
5816   _nodal_connec_index->decrRef();
5817   _nodal_connec_index=newConnI.retn();
5818   computeTypes();
5819   updateTime();
5820   return ret.retn();
5821 }
5822
5823 /*!
5824  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5825  * so that the number of cells remains the same. Quadratic faces are converted to
5826  * polygons. This method works only for 2D meshes in
5827  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5828  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5829  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5830  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5831  *         a polylinized edge constituting the input polygon.
5832  *  \throw If the coordinates array is not set.
5833  *  \throw If the nodal connectivity of cells is not defined.
5834  *  \throw If \a this->getMeshDimension() != 2.
5835  *  \throw If \a this->getSpaceDimension() != 2.
5836  */
5837 void MEDCouplingUMesh::tessellate2DInternal(double eps)
5838 {
5839   checkFullyDefined();
5840   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5841     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5842   double epsa=fabs(eps);
5843   if(epsa<std::numeric_limits<double>::min())
5844     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 !");
5845   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
5846   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
5847   revDesc1=0; revDescIndx1=0;
5848   mDesc->tessellate2D(eps);
5849   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5850   setCoords(mDesc->getCoords());
5851 }
5852
5853 /*!
5854  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
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 radian) between 2 sub-edges of
5857  *         a sub-divided edge.
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() != 1.
5861  *  \throw If \a this->getSpaceDimension() != 2.
5862  */
5863 void MEDCouplingUMesh::tessellate2DCurveInternal(double eps)
5864 {
5865   checkFullyDefined();
5866   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5867     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal works on umeshes with meshdim equal to 1 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::tessellate2DCurveInternal : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5871   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5872   int nbCells=getNumberOfCells();
5873   int nbNodes=getNumberOfNodes();
5874   const int *conn=_nodal_connec->getConstPointer();
5875   const int *connI=_nodal_connec_index->getConstPointer();
5876   const double *coords=_coords->getConstPointer();
5877   std::vector<double> addCoo;
5878   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5879   MCAuto<DataArrayInt> newConnI(DataArrayInt::New());
5880   newConnI->alloc(nbCells+1,1);
5881   int *newConnIPtr=newConnI->getPointer();
5882   *newConnIPtr=0;
5883   int tmp1[3];
5884   INTERP_KERNEL::Node *tmp2[3];
5885   std::set<INTERP_KERNEL::NormalizedCellType> types;
5886   for(int i=0;i<nbCells;i++,newConnIPtr++)
5887     {
5888       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5889       if(cm.isQuadratic())
5890         {//assert(connI[i+1]-connI[i]-1==3)
5891           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5892           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5893           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5894           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5895           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5896           if(eac)
5897             {
5898               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5899               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5900               delete eac;
5901               newConnIPtr[1]=(int)newConn.size();
5902             }
5903           else
5904             {
5905               types.insert(INTERP_KERNEL::NORM_SEG2);
5906               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5907               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5908               newConnIPtr[1]=newConnIPtr[0]+3;
5909             }
5910         }
5911       else
5912         {
5913           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5914           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5915           newConnIPtr[1]=newConnIPtr[0]+3;
5916         }
5917     }
5918   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5919     return ;
5920   _types=types;
5921   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5922   MCAuto<DataArrayInt> newConnArr=DataArrayInt::New();
5923   newConnArr->alloc((int)newConn.size(),1);
5924   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5925   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5926   MCAuto<DataArrayDouble> newCoords=DataArrayDouble::New();
5927   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5928   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5929   std::copy(addCoo.begin(),addCoo.end(),work);
5930   DataArrayDouble::SetArrayIn(newCoords,_coords);
5931   updateTime();
5932 }
5933
5934 /*!
5935  * 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.
5936  * This method completly ignore coordinates.
5937  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5938  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5939  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5940  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5941  */
5942 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5943 {
5944   checkFullyDefined();
5945   if(getMeshDimension()!=2)
5946     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5947   int nbOfCells=getNumberOfCells();
5948   int *connI=_nodal_connec_index->getPointer();
5949   int newConnLgth=0;
5950   for(int i=0;i<nbOfCells;i++,connI++)
5951     {
5952       int offset=descIndex[i];
5953       int nbOfEdges=descIndex[i+1]-offset;
5954       //
5955       bool ddirect=desc[offset+nbOfEdges-1]>0;
5956       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5957       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5958       for(int j=0;j<nbOfEdges;j++)
5959         {
5960           bool direct=desc[offset+j]>0;
5961           int edgeId=std::abs(desc[offset+j])-1;
5962           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5963             {
5964               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5965               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5966               int ref2=direct?id1:id2;
5967               if(ref==ref2)
5968                 {
5969                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5970                   newConnLgth+=nbOfSubNodes-1;
5971                   ref=direct?id2:id1;
5972                 }
5973               else
5974                 {
5975                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5976                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5977                 }
5978             }
5979           else
5980             {
5981               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5982             }
5983         }
5984       newConnLgth++;//+1 is for cell type
5985       connI[1]=newConnLgth;
5986     }
5987   //
5988   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5989   newConn->alloc(newConnLgth,1);
5990   int *work=newConn->getPointer();
5991   for(int i=0;i<nbOfCells;i++)
5992     {
5993       *work++=INTERP_KERNEL::NORM_POLYGON;
5994       int offset=descIndex[i];
5995       int nbOfEdges=descIndex[i+1]-offset;
5996       for(int j=0;j<nbOfEdges;j++)
5997         {
5998           bool direct=desc[offset+j]>0;
5999           int edgeId=std::abs(desc[offset+j])-1;
6000           if(direct)
6001             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
6002           else
6003             {
6004               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
6005               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
6006               work=std::copy(it,it+nbOfSubNodes-1,work);
6007             }
6008         }
6009     }
6010   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
6011   _types.clear();
6012   if(nbOfCells>0)
6013     _types.insert(INTERP_KERNEL::NORM_POLYGON);
6014 }
6015
6016 /*!
6017  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
6018  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
6019  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
6020  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
6021  * so it can be useful to call mergeNodes() before calling this method.
6022  *  \throw If \a this->getMeshDimension() <= 1.
6023  *  \throw If the coordinates array is not set.
6024  *  \throw If the nodal connectivity of cells is not defined.
6025  */
6026 void MEDCouplingUMesh::convertDegeneratedCells()
6027 {
6028   checkFullyDefined();
6029   if(getMeshDimension()<=1)
6030     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
6031   int nbOfCells=getNumberOfCells();
6032   if(nbOfCells<1)
6033     return ;
6034   int initMeshLgth=getNodalConnectivityArrayLen();
6035   int *conn=_nodal_connec->getPointer();
6036   int *index=_nodal_connec_index->getPointer();
6037   int posOfCurCell=0;
6038   int newPos=0;
6039   int lgthOfCurCell;
6040   for(int i=0;i<nbOfCells;i++)
6041     {
6042       lgthOfCurCell=index[i+1]-posOfCurCell;
6043       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
6044       int newLgth;
6045       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
6046                                                                                                      conn+newPos+1,newLgth);
6047       conn[newPos]=newType;
6048       newPos+=newLgth+1;
6049       posOfCurCell=index[i+1];
6050       index[i+1]=newPos;
6051     }
6052   if(newPos!=initMeshLgth)
6053     _nodal_connec->reAlloc(newPos);
6054   computeTypes();
6055 }
6056
6057 /*!
6058  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
6059  * A cell is considered to be oriented correctly if an angle between its
6060  * normal vector and a given vector is less than \c PI / \c 2.
6061  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6062  *         cells. 
6063  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6064  *         checked.
6065  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6066  *         is not cleared before filling in.
6067  *  \throw If \a this->getMeshDimension() != 2.
6068  *  \throw If \a this->getSpaceDimension() != 3.
6069  *
6070  *  \if ENABLE_EXAMPLES
6071  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6072  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6073  *  \endif
6074  */
6075 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6076 {
6077   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6078     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6079   int nbOfCells=getNumberOfCells();
6080   const int *conn=_nodal_connec->getConstPointer();
6081   const int *connI=_nodal_connec_index->getConstPointer();
6082   const double *coordsPtr=_coords->getConstPointer();
6083   for(int i=0;i<nbOfCells;i++)
6084     {
6085       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6086       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6087         {
6088           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6089           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6090             cells.push_back(i);
6091         }
6092     }
6093 }
6094
6095 /*!
6096  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6097  * considered to be oriented correctly if an angle between its normal vector and a
6098  * given vector is less than \c PI / \c 2. 
6099  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6100  *         cells. 
6101  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6102  *         checked.
6103  *  \throw If \a this->getMeshDimension() != 2.
6104  *  \throw If \a this->getSpaceDimension() != 3.
6105  *
6106  *  \if ENABLE_EXAMPLES
6107  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6108  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6109  *  \endif
6110  *
6111  *  \sa changeOrientationOfCells
6112  */
6113 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6114 {
6115   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6116     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6117   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6118   const int *connI(_nodal_connec_index->getConstPointer());
6119   const double *coordsPtr(_coords->getConstPointer());
6120   bool isModified(false);
6121   for(int i=0;i<nbOfCells;i++)
6122     {
6123       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6124       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6125         {
6126           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6127           bool isQuadratic(cm.isQuadratic());
6128           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6129             {
6130               isModified=true;
6131               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6132             }
6133         }
6134     }
6135   if(isModified)
6136     _nodal_connec->declareAsNew();
6137   updateTime();
6138 }
6139
6140 /*!
6141  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6142  *
6143  * \sa orientCorrectly2DCells
6144  */
6145 void MEDCouplingUMesh::changeOrientationOfCells()
6146 {
6147   int mdim(getMeshDimension());
6148   if(mdim!=2 && mdim!=1)
6149     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6150   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6151   const int *connI(_nodal_connec_index->getConstPointer());
6152   if(mdim==2)
6153     {//2D
6154       for(int i=0;i<nbOfCells;i++)
6155         {
6156           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6157           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6158           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6159         }
6160     }
6161   else
6162     {//1D
6163       for(int i=0;i<nbOfCells;i++)
6164         {
6165           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6166           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6167           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6168         }
6169     }
6170 }
6171
6172 /*!
6173  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6174  * oriented facets. The normal vector of the facet should point out of the cell.
6175  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6176  *         is not cleared before filling in.
6177  *  \throw If \a this->getMeshDimension() != 3.
6178  *  \throw If \a this->getSpaceDimension() != 3.
6179  *  \throw If the coordinates array is not set.
6180  *  \throw If the nodal connectivity of cells is not defined.
6181  *
6182  *  \if ENABLE_EXAMPLES
6183  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6184  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6185  *  \endif
6186  */
6187 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6188 {
6189   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6190     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6191   int nbOfCells=getNumberOfCells();
6192   const int *conn=_nodal_connec->getConstPointer();
6193   const int *connI=_nodal_connec_index->getConstPointer();
6194   const double *coordsPtr=_coords->getConstPointer();
6195   for(int i=0;i<nbOfCells;i++)
6196     {
6197       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6198       if(type==INTERP_KERNEL::NORM_POLYHED)
6199         {
6200           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6201             cells.push_back(i);
6202         }
6203     }
6204 }
6205
6206 /*!
6207  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6208  * out of the cell. 
6209  *  \throw If \a this->getMeshDimension() != 3.
6210  *  \throw If \a this->getSpaceDimension() != 3.
6211  *  \throw If the coordinates array is not set.
6212  *  \throw If the nodal connectivity of cells is not defined.
6213  *  \throw If the reparation fails.
6214  *
6215  *  \if ENABLE_EXAMPLES
6216  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6217  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6218  *  \endif
6219  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6220  */
6221 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6222 {
6223   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6224     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6225   int nbOfCells=getNumberOfCells();
6226   int *conn=_nodal_connec->getPointer();
6227   const int *connI=_nodal_connec_index->getConstPointer();
6228   const double *coordsPtr=_coords->getConstPointer();
6229   for(int i=0;i<nbOfCells;i++)
6230     {
6231       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6232       if(type==INTERP_KERNEL::NORM_POLYHED)
6233         {
6234           try
6235           {
6236               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6237                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6238           }
6239           catch(INTERP_KERNEL::Exception& e)
6240           {
6241               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6242               throw INTERP_KERNEL::Exception(oss.str().c_str());
6243           }
6244         }
6245     }
6246   updateTime();
6247 }
6248
6249 /*!
6250  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6251  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6252  * according to which the first facet of the cell should be oriented to have the normal vector
6253  * pointing out of cell.
6254  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6255  *         cells. The caller is to delete this array using decrRef() as it is no more
6256  *         needed. 
6257  *  \throw If \a this->getMeshDimension() != 3.
6258  *  \throw If \a this->getSpaceDimension() != 3.
6259  *  \throw If the coordinates array is not set.
6260  *  \throw If the nodal connectivity of cells is not defined.
6261  *
6262  *  \if ENABLE_EXAMPLES
6263  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6264  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6265  *  \endif
6266  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6267  */
6268 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6269 {
6270   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6271   if(getMeshDimension()!=3)
6272     throw INTERP_KERNEL::Exception(msg);
6273   int spaceDim=getSpaceDimension();
6274   if(spaceDim!=3)
6275     throw INTERP_KERNEL::Exception(msg);
6276   //
6277   int nbOfCells=getNumberOfCells();
6278   int *conn=_nodal_connec->getPointer();
6279   const int *connI=_nodal_connec_index->getConstPointer();
6280   const double *coo=getCoords()->getConstPointer();
6281   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6282   for(int i=0;i<nbOfCells;i++)
6283     {
6284       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6285       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6286         {
6287           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6288             {
6289               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6290               cells->pushBackSilent(i);
6291             }
6292         }
6293     }
6294   return cells.retn();
6295 }
6296
6297 /*!
6298  * This method is a faster method to correct orientation of all 3D cells in \a this.
6299  * 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.
6300  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
6301  * 
6302  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6303  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6304  */
6305 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6306 {
6307   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6308     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6309   int nbOfCells=getNumberOfCells();
6310   int *conn=_nodal_connec->getPointer();
6311   const int *connI=_nodal_connec_index->getConstPointer();
6312   const double *coordsPtr=_coords->getConstPointer();
6313   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6314   for(int i=0;i<nbOfCells;i++)
6315     {
6316       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6317       switch(type)
6318       {
6319         case INTERP_KERNEL::NORM_TETRA4:
6320           {
6321             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6322               {
6323                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6324                 ret->pushBackSilent(i);
6325               }
6326             break;
6327           }
6328         case INTERP_KERNEL::NORM_PYRA5:
6329           {
6330             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6331               {
6332                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6333                 ret->pushBackSilent(i);
6334               }
6335             break;
6336           }
6337         case INTERP_KERNEL::NORM_PENTA6:
6338         case INTERP_KERNEL::NORM_HEXA8:
6339         case INTERP_KERNEL::NORM_HEXGP12:
6340           {
6341             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6342               {
6343                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6344                 ret->pushBackSilent(i);
6345               }
6346             break;
6347           }
6348         case INTERP_KERNEL::NORM_POLYHED:
6349           {
6350             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6351               {
6352                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6353                 ret->pushBackSilent(i);
6354               }
6355             break;
6356           }
6357         default:
6358           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 !");
6359       }
6360     }
6361   updateTime();
6362   return ret.retn();
6363 }
6364
6365 /*!
6366  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6367  * If it is not the case an exception will be thrown.
6368  * This method is fast because the first cell of \a this is used to compute the plane.
6369  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6370  * \param pos output of size at least 3 used to store a point owned of searched plane.
6371  */
6372 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6373 {
6374   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6375     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6376   const int *conn=_nodal_connec->getConstPointer();
6377   const int *connI=_nodal_connec_index->getConstPointer();
6378   const double *coordsPtr=_coords->getConstPointer();
6379   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6380   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6381 }
6382
6383 /*!
6384  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6385  * cells. Currently cells of the following types are treated:
6386  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6387  * For a cell of other type an exception is thrown.
6388  * Space dimension of a 2D mesh can be either 2 or 3.
6389  * The Edge Ratio of a cell \f$t\f$ is: 
6390  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6391  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6392  *  the smallest edge lengths of \f$t\f$.
6393  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6394  *          cells and one time, lying on \a this mesh. The caller is to delete this
6395  *          field using decrRef() as it is no more needed. 
6396  *  \throw If the coordinates array is not set.
6397  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6398  *  \throw If the connectivity data array has more than one component.
6399  *  \throw If the connectivity data array has a named component.
6400  *  \throw If the connectivity index data array has more than one component.
6401  *  \throw If the connectivity index data array has a named component.
6402  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6403  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6404  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6405  */
6406 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6407 {
6408   checkConsistencyLight();
6409   int spaceDim=getSpaceDimension();
6410   int meshDim=getMeshDimension();
6411   if(spaceDim!=2 && spaceDim!=3)
6412     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6413   if(meshDim!=2 && meshDim!=3)
6414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6415   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6416   ret->setMesh(this);
6417   int nbOfCells=getNumberOfCells();
6418   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6419   arr->alloc(nbOfCells,1);
6420   double *pt=arr->getPointer();
6421   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6422   const int *conn=_nodal_connec->getConstPointer();
6423   const int *connI=_nodal_connec_index->getConstPointer();
6424   const double *coo=_coords->getConstPointer();
6425   double tmp[12];
6426   for(int i=0;i<nbOfCells;i++,pt++)
6427     {
6428       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6429       switch(t)
6430       {
6431         case INTERP_KERNEL::NORM_TRI3:
6432           {
6433             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6434             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6435             break;
6436           }
6437         case INTERP_KERNEL::NORM_QUAD4:
6438           {
6439             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6440             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6441             break;
6442           }
6443         case INTERP_KERNEL::NORM_TETRA4:
6444           {
6445             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6446             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6447             break;
6448           }
6449         default:
6450           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6451       }
6452       conn+=connI[i+1]-connI[i];
6453     }
6454   ret->setName("EdgeRatio");
6455   ret->synchronizeTimeWithSupport();
6456   return ret.retn();
6457 }
6458
6459 /*!
6460  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6461  * cells. Currently cells of the following types are treated:
6462  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6463  * For a cell of other type an exception is thrown.
6464  * Space dimension of a 2D mesh can be either 2 or 3.
6465  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6466  *          cells and one time, lying on \a this mesh. The caller is to delete this
6467  *          field using decrRef() as it is no more needed. 
6468  *  \throw If the coordinates array is not set.
6469  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6470  *  \throw If the connectivity data array has more than one component.
6471  *  \throw If the connectivity data array has a named component.
6472  *  \throw If the connectivity index data array has more than one component.
6473  *  \throw If the connectivity index data array has a named component.
6474  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6475  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6476  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6477  */
6478 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6479 {
6480   checkConsistencyLight();
6481   int spaceDim=getSpaceDimension();
6482   int meshDim=getMeshDimension();
6483   if(spaceDim!=2 && spaceDim!=3)
6484     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6485   if(meshDim!=2 && meshDim!=3)
6486     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6487   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6488   ret->setMesh(this);
6489   int nbOfCells=getNumberOfCells();
6490   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6491   arr->alloc(nbOfCells,1);
6492   double *pt=arr->getPointer();
6493   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6494   const int *conn=_nodal_connec->getConstPointer();
6495   const int *connI=_nodal_connec_index->getConstPointer();
6496   const double *coo=_coords->getConstPointer();
6497   double tmp[12];
6498   for(int i=0;i<nbOfCells;i++,pt++)
6499     {
6500       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6501       switch(t)
6502       {
6503         case INTERP_KERNEL::NORM_TRI3:
6504           {
6505             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6506             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6507             break;
6508           }
6509         case INTERP_KERNEL::NORM_QUAD4:
6510           {
6511             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6512             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6513             break;
6514           }
6515         case INTERP_KERNEL::NORM_TETRA4:
6516           {
6517             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6518             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6519             break;
6520           }
6521         default:
6522           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6523       }
6524       conn+=connI[i+1]-connI[i];
6525     }
6526   ret->setName("AspectRatio");
6527   ret->synchronizeTimeWithSupport();
6528   return ret.retn();
6529 }
6530
6531 /*!
6532  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6533  * cells of \a this 2D mesh in 3D space. It is a measure of the "planarity" of 2D cell
6534  * in 3D space. Currently only cells of the following types are
6535  * treated: INTERP_KERNEL::NORM_QUAD4.
6536  * For a cell of other type an exception is thrown.
6537  * The warp field is computed as follows: let (a,b,c,d) be the points of the quad.
6538  * Defining
6539  * \f$t=\vec{da}\times\vec{ab}\f$,
6540  * \f$u=\vec{ab}\times\vec{bc}\f$
6541  * \f$v=\vec{bc}\times\vec{cd}\f$
6542  * \f$w=\vec{cd}\times\vec{da}\f$, the warp is defined as \f$W^3\f$ with
6543  *  \f[
6544  *     W=min(\frac{t}{|t|}\cdot\frac{v}{|v|}, \frac{u}{|u|}\cdot\frac{w}{|w|})
6545  *  \f]
6546  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6547  *          cells and one time, lying on \a this mesh. The caller is to delete this
6548  *          field using decrRef() as it is no more needed. 
6549  *  \throw If the coordinates array is not set.
6550  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6551  *  \throw If the connectivity data array has more than one component.
6552  *  \throw If the connectivity data array has a named component.
6553  *  \throw If the connectivity index data array has more than one component.
6554  *  \throw If the connectivity index data array has a named component.
6555  *  \throw If \a this->getMeshDimension() != 2.
6556  *  \throw If \a this->getSpaceDimension() != 3.
6557  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6558  */
6559 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6560 {
6561   checkConsistencyLight();
6562   int spaceDim=getSpaceDimension();
6563   int meshDim=getMeshDimension();
6564   if(spaceDim!=3)
6565     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6566   if(meshDim!=2)
6567     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6568   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6569   ret->setMesh(this);
6570   int nbOfCells=getNumberOfCells();
6571   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6572   arr->alloc(nbOfCells,1);
6573   double *pt=arr->getPointer();
6574   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6575   const int *conn=_nodal_connec->getConstPointer();
6576   const int *connI=_nodal_connec_index->getConstPointer();
6577   const double *coo=_coords->getConstPointer();
6578   double tmp[12];
6579   for(int i=0;i<nbOfCells;i++,pt++)
6580     {
6581       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6582       switch(t)
6583       {
6584         case INTERP_KERNEL::NORM_QUAD4:
6585           {
6586             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6587             *pt=INTERP_KERNEL::quadWarp(tmp);
6588             break;
6589           }
6590         default:
6591           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6592       }
6593       conn+=connI[i+1]-connI[i];
6594     }
6595   ret->setName("Warp");
6596   ret->synchronizeTimeWithSupport();
6597   return ret.retn();
6598 }
6599
6600
6601 /*!
6602  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6603  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6604  * treated: INTERP_KERNEL::NORM_QUAD4.
6605  * The skew is computed as follow for a quad with points (a,b,c,d): let
6606  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
6607  * then the skew is computed as:
6608  *  \f[
6609  *    s=\frac{u}{|u|}\cdot\frac{v}{|v|}
6610  *  \f]
6611  *
6612  * For a cell of other type an exception is thrown.
6613  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6614  *          cells and one time, lying on \a this mesh. The caller is to delete this
6615  *          field using decrRef() as it is no more needed. 
6616  *  \throw If the coordinates array is not set.
6617  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6618  *  \throw If the connectivity data array has more than one component.
6619  *  \throw If the connectivity data array has a named component.
6620  *  \throw If the connectivity index data array has more than one component.
6621  *  \throw If the connectivity index data array has a named component.
6622  *  \throw If \a this->getMeshDimension() != 2.
6623  *  \throw If \a this->getSpaceDimension() != 3.
6624  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6625  */
6626 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6627 {
6628   checkConsistencyLight();
6629   int spaceDim=getSpaceDimension();
6630   int meshDim=getMeshDimension();
6631   if(spaceDim!=3)
6632     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6633   if(meshDim!=2)
6634     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6635   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6636   ret->setMesh(this);
6637   int nbOfCells=getNumberOfCells();
6638   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6639   arr->alloc(nbOfCells,1);
6640   double *pt=arr->getPointer();
6641   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6642   const int *conn=_nodal_connec->getConstPointer();
6643   const int *connI=_nodal_connec_index->getConstPointer();
6644   const double *coo=_coords->getConstPointer();
6645   double tmp[12];
6646   for(int i=0;i<nbOfCells;i++,pt++)
6647     {
6648       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6649       switch(t)
6650       {
6651         case INTERP_KERNEL::NORM_QUAD4:
6652           {
6653             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6654             *pt=INTERP_KERNEL::quadSkew(tmp);
6655             break;
6656           }
6657         default:
6658           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6659       }
6660       conn+=connI[i+1]-connI[i];
6661     }
6662   ret->setName("Skew");
6663   ret->synchronizeTimeWithSupport();
6664   return ret.retn();
6665 }
6666
6667 /*!
6668  * 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.
6669  *
6670  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6671  *
6672  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6673  */
6674 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6675 {
6676   checkConsistencyLight();
6677   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6678   ret->setMesh(this);
6679   std::set<INTERP_KERNEL::NormalizedCellType> types;
6680   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6681   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6682   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6683   arr->alloc(nbCells,1);
6684   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6685     {
6686       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6687       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
6688       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6689     }
6690   ret->setArray(arr);
6691   ret->setName("Diameter");
6692   return ret.retn();
6693 }
6694
6695 /*!
6696  * This method aggregate the bbox of each cell and put it into bbox parameter.
6697  * 
6698  * \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)
6699  *                         For all other cases this input parameter is ignored.
6700  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6701  * 
6702  * \throw If \a this is not fully set (coordinates and connectivity).
6703  * \throw If a cell in \a this has no valid nodeId.
6704  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6705  */
6706 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6707 {
6708   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6709   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.
6710     return getBoundingBoxForBBTreeFast();
6711   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6712     {
6713       bool presenceOfQuadratic(false);
6714       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6715         {
6716           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6717           if(cm.isQuadratic())
6718             presenceOfQuadratic=true;
6719         }
6720       if(!presenceOfQuadratic)
6721         return getBoundingBoxForBBTreeFast();
6722       if(mDim==2 && sDim==2)
6723         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6724       else
6725         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6726     }
6727   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) !");
6728 }
6729
6730 /*!
6731  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6732  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6733  * 
6734  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6735  * 
6736  * \throw If \a this is not fully set (coordinates and connectivity).
6737  * \throw If a cell in \a this has no valid nodeId.
6738  */
6739 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6740 {
6741   checkFullyDefined();
6742   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6743   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6744   double *bbox(ret->getPointer());
6745   for(int i=0;i<nbOfCells*spaceDim;i++)
6746     {
6747       bbox[2*i]=std::numeric_limits<double>::max();
6748       bbox[2*i+1]=-std::numeric_limits<double>::max();
6749     }
6750   const double *coordsPtr(_coords->getConstPointer());
6751   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6752   for(int i=0;i<nbOfCells;i++)
6753     {
6754       int offset=connI[i]+1;
6755       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6756       for(int j=0;j<nbOfNodesForCell;j++)
6757         {
6758           int nodeId=conn[offset+j];
6759           if(nodeId>=0 && nodeId<nbOfNodes)
6760             {
6761               for(int k=0;k<spaceDim;k++)
6762                 {
6763                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6764                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6765                 }
6766               kk++;
6767             }
6768         }
6769       if(kk==0)
6770         {
6771           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6772           throw INTERP_KERNEL::Exception(oss.str().c_str());
6773         }
6774     }
6775   return ret.retn();
6776 }
6777
6778 /*!
6779  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6780  * useful for 2D meshes having quadratic cells
6781  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6782  * the two extremities of the arc of circle).
6783  * 
6784  * \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)
6785  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6786  * \throw If \a this is not fully defined.
6787  * \throw If \a this is not a mesh with meshDimension equal to 2.
6788  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6789  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6790  */
6791 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6792 {
6793   checkFullyDefined();
6794   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6795   if(spaceDim!=2 || mDim!=2)
6796     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!");
6797   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6798   double *bbox(ret->getPointer());
6799   const double *coords(_coords->getConstPointer());
6800   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6801   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6802     {
6803       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6804       int sz(connI[1]-connI[0]-1);
6805       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6806       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6807       INTERP_KERNEL::QuadraticPolygon *pol(0);
6808       for(int j=0;j<sz;j++)
6809         {
6810           int nodeId(conn[*connI+1+j]);
6811           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6812         }
6813       if(!cm.isQuadratic())
6814         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6815       else
6816         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6817       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6818       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6819     }
6820   return ret.retn();
6821 }
6822
6823 /*!
6824  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6825  * useful for 2D meshes having quadratic cells
6826  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6827  * the two extremities of the arc of circle).
6828  * 
6829  * \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)
6830  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6831  * \throw If \a this is not fully defined.
6832  * \throw If \a this is not a mesh with meshDimension equal to 1.
6833  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6834  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6835  */
6836 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6837 {
6838   checkFullyDefined();
6839   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6840   if(spaceDim!=2 || mDim!=1)
6841     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!");
6842   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6843   double *bbox(ret->getPointer());
6844   const double *coords(_coords->getConstPointer());
6845   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6846   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6847     {
6848       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6849       int sz(connI[1]-connI[0]-1);
6850       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6851       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6852       INTERP_KERNEL::Edge *edge(0);
6853       for(int j=0;j<sz;j++)
6854         {
6855           int nodeId(conn[*connI+1+j]);
6856           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6857         }
6858       if(!cm.isQuadratic())
6859         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6860       else
6861         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6862       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6863       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6864     }
6865   return ret.retn();
6866 }
6867
6868 /// @cond INTERNAL
6869
6870 namespace MEDCouplingImpl
6871 {
6872   class ConnReader
6873   {
6874   public:
6875     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6876     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6877   private:
6878     const int *_conn;
6879     int _val;
6880   };
6881
6882   class ConnReader2
6883   {
6884   public:
6885     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6886     bool operator() (const int& pos) { return _conn[pos]==_val; }
6887   private:
6888     const int *_conn;
6889     int _val;
6890   };
6891 }
6892
6893 /// @endcond
6894
6895 /*!
6896  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6897  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6898  * \a this is composed in cell types.
6899  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6900  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6901  * This parameter is kept only for compatibility with other methode listed above.
6902  */
6903 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6904 {
6905   checkConnectivityFullyDefined();
6906   const int *conn=_nodal_connec->getConstPointer();
6907   const int *connI=_nodal_connec_index->getConstPointer();
6908   const int *work=connI;
6909   int nbOfCells=getNumberOfCells();
6910   std::size_t n=getAllGeoTypes().size();
6911   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6912   std::set<INTERP_KERNEL::NormalizedCellType> types;
6913   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6914     {
6915       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6916       if(types.find(typ)!=types.end())
6917         {
6918           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6919           oss << " is not contiguous !";
6920           throw INTERP_KERNEL::Exception(oss.str().c_str());
6921         }
6922       types.insert(typ);
6923       ret[3*i]=typ;
6924       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
6925       ret[3*i+1]=(int)std::distance(work,work2);
6926       work=work2;
6927     }
6928   return ret;
6929 }
6930
6931 /*!
6932  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6933  * only for types cell, type node is not managed.
6934  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6935  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6936  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6937  * If 2 or more same geometric type is in \a code and exception is thrown too.
6938  *
6939  * This method firstly checks
6940  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6941  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6942  * an exception is thrown too.
6943  * 
6944  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6945  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6946  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6947  */
6948 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6949 {
6950   if(code.empty())
6951     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6952   std::size_t sz=code.size();
6953   std::size_t n=sz/3;
6954   if(sz%3!=0)
6955     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6956   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6957   int nb=0;
6958   bool isNoPflUsed=true;
6959   for(std::size_t i=0;i<n;i++)
6960     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6961       {
6962         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6963         nb+=code[3*i+1];
6964         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6965           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6966         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6967       }
6968   if(types.size()!=n)
6969     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6970   if(isNoPflUsed)
6971     {
6972       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6973         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6974       if(types.size()==_types.size())
6975         return 0;
6976     }
6977   MCAuto<DataArrayInt> ret=DataArrayInt::New();
6978   ret->alloc(nb,1);
6979   int *retPtr=ret->getPointer();
6980   const int *connI=_nodal_connec_index->getConstPointer();
6981   const int *conn=_nodal_connec->getConstPointer();
6982   int nbOfCells=getNumberOfCells();
6983   const int *i=connI;
6984   int kk=0;
6985   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6986     {
6987       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
6988       int offset=(int)std::distance(connI,i);
6989       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
6990       int nbOfCellsOfCurType=(int)std::distance(i,j);
6991       if(code[3*kk+2]==-1)
6992         for(int k=0;k<nbOfCellsOfCurType;k++)
6993           *retPtr++=k+offset;
6994       else
6995         {
6996           int idInIdsPerType=code[3*kk+2];
6997           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6998             {
6999               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
7000               if(zePfl)
7001                 {
7002                   zePfl->checkAllocated();
7003                   if(zePfl->getNumberOfComponents()==1)
7004                     {
7005                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
7006                         {
7007                           if(*k>=0 && *k<nbOfCellsOfCurType)
7008                             *retPtr=(*k)+offset;
7009                           else
7010                             {
7011                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
7012                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
7013                               throw INTERP_KERNEL::Exception(oss.str().c_str());
7014                             }
7015                         }
7016                     }
7017                   else
7018                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
7019                 }
7020               else
7021                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
7022             }
7023           else
7024             {
7025               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
7026               oss << " should be in [0," << idsPerType.size() << ") !";
7027               throw INTERP_KERNEL::Exception(oss.str().c_str());
7028             }
7029         }
7030       i=j;
7031     }
7032   return ret.retn();
7033 }
7034
7035 /*!
7036  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
7037  * 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.
7038  * 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.
7039  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
7040  * 
7041  * \param [in] profile
7042  * \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.
7043  * \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,
7044  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
7045  * \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.
7046  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
7047  * \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
7048  */
7049 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
7050 {
7051   if(!profile)
7052     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
7053   if(profile->getNumberOfComponents()!=1)
7054     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
7055   checkConnectivityFullyDefined();
7056   const int *conn=_nodal_connec->getConstPointer();
7057   const int *connI=_nodal_connec_index->getConstPointer();
7058   int nbOfCells=getNumberOfCells();
7059   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7060   std::vector<int> typeRangeVals(1);
7061   for(const int *i=connI;i!=connI+nbOfCells;)
7062     {
7063       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7064       if(std::find(types.begin(),types.end(),curType)!=types.end())
7065         {
7066           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
7067         }
7068       types.push_back(curType);
7069       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7070       typeRangeVals.push_back((int)std::distance(connI,i));
7071     }
7072   //
7073   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
7074   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
7075   MCAuto<DataArrayInt> tmp0=castArr;
7076   MCAuto<DataArrayInt> tmp1=rankInsideCast;
7077   MCAuto<DataArrayInt> tmp2=castsPresent;
7078   //
7079   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
7080   code.resize(3*nbOfCastsFinal);
7081   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
7082   std::vector< MCAuto<DataArrayInt> > idsPerType2;
7083   for(int i=0;i<nbOfCastsFinal;i++)
7084     {
7085       int castId=castsPresent->getIJ(i,0);
7086       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
7087       idsInPflPerType2.push_back(tmp3);
7088       code[3*i]=(int)types[castId];
7089       code[3*i+1]=tmp3->getNumberOfTuples();
7090       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7091       if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
7092         {
7093           tmp4->copyStringInfoFrom(*profile);
7094           idsPerType2.push_back(tmp4);
7095           code[3*i+2]=(int)idsPerType2.size()-1;
7096         }
7097       else
7098         {
7099           code[3*i+2]=-1;
7100         }
7101     }
7102   std::size_t sz2=idsInPflPerType2.size();
7103   idsInPflPerType.resize(sz2);
7104   for(std::size_t i=0;i<sz2;i++)
7105     {
7106       DataArrayInt *locDa=idsInPflPerType2[i];
7107       locDa->incrRef();
7108       idsInPflPerType[i]=locDa;
7109     }
7110   std::size_t sz=idsPerType2.size();
7111   idsPerType.resize(sz);
7112   for(std::size_t i=0;i<sz;i++)
7113     {
7114       DataArrayInt *locDa=idsPerType2[i];
7115       locDa->incrRef();
7116       idsPerType[i]=locDa;
7117     }
7118 }
7119
7120 /*!
7121  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7122  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7123  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7124  * 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.
7125  */
7126 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7127 {
7128   checkFullyDefined();
7129   nM1LevMesh->checkFullyDefined();
7130   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7131     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7132   if(_coords!=nM1LevMesh->getCoords())
7133     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7134   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
7135   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
7136   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7137   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7138   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7139   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7140   tmp->setConnectivity(tmp0,tmp1);
7141   tmp->renumberCells(ret0->getConstPointer(),false);
7142   revDesc=tmp->getNodalConnectivity();
7143   revDescIndx=tmp->getNodalConnectivityIndex();
7144   DataArrayInt *ret=0;
7145   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7146     {
7147       int tmp2;
7148       ret->getMaxValue(tmp2);
7149       ret->decrRef();
7150       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7151       throw INTERP_KERNEL::Exception(oss.str().c_str());
7152     }
7153   nM1LevMeshIds=ret;
7154   //
7155   revDesc->incrRef();
7156   revDescIndx->incrRef();
7157   ret1->incrRef();
7158   ret0->incrRef();
7159   meshnM1Old2New=ret0;
7160   return ret1;
7161 }
7162
7163 /*!
7164  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7165  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7166  * in "Old to New" mode.
7167  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7168  *          this array using decrRef() as it is no more needed.
7169  *  \throw If the nodal connectivity of cells is not defined.
7170  */
7171 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7172 {
7173   checkConnectivityFullyDefined();
7174   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7175   renumberCells(ret->getConstPointer(),false);
7176   return ret.retn();
7177 }
7178
7179 /*!
7180  * This methods checks that cells are sorted by their types.
7181  * This method makes asumption (no check) that connectivity is correctly set before calling.
7182  */
7183 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7184 {
7185   checkFullyDefined();
7186   const int *conn=_nodal_connec->getConstPointer();
7187   const int *connI=_nodal_connec_index->getConstPointer();
7188   int nbOfCells=getNumberOfCells();
7189   std::set<INTERP_KERNEL::NormalizedCellType> types;
7190   for(const int *i=connI;i!=connI+nbOfCells;)
7191     {
7192       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7193       if(types.find(curType)!=types.end())
7194         return false;
7195       types.insert(curType);
7196       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7197     }
7198   return true;
7199 }
7200
7201 /*!
7202  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7203  * The geometric type order is specified by MED file.
7204  * 
7205  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7206  */
7207 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7208 {
7209   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7210 }
7211
7212 /*!
7213  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7214  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7215  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7216  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7217  */
7218 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7219 {
7220   checkFullyDefined();
7221   const int *conn=_nodal_connec->getConstPointer();
7222   const int *connI=_nodal_connec_index->getConstPointer();
7223   int nbOfCells=getNumberOfCells();
7224   if(nbOfCells==0)
7225     return true;
7226   int lastPos=-1;
7227   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7228   for(const int *i=connI;i!=connI+nbOfCells;)
7229     {
7230       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7231       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7232       if(isTypeExists!=orderEnd)
7233         {
7234           int pos=(int)std::distance(orderBg,isTypeExists);
7235           if(pos<=lastPos)
7236             return false;
7237           lastPos=pos;
7238           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7239         }
7240       else
7241         {
7242           if(sg.find(curType)==sg.end())
7243             {
7244               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7245               sg.insert(curType);
7246             }
7247           else
7248             return false;
7249         }
7250     }
7251   return true;
7252 }
7253
7254 /*!
7255  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7256  * 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
7257  * 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'.
7258  */
7259 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7260 {
7261   checkConnectivityFullyDefined();
7262   int nbOfCells=getNumberOfCells();
7263   const int *conn=_nodal_connec->getConstPointer();
7264   const int *connI=_nodal_connec_index->getConstPointer();
7265   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
7266   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
7267   tmpa->alloc(nbOfCells,1);
7268   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7269   tmpb->fillWithZero();
7270   int *tmp=tmpa->getPointer();
7271   int *tmp2=tmpb->getPointer();
7272   for(const int *i=connI;i!=connI+nbOfCells;i++)
7273     {
7274       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7275       if(where!=orderEnd)
7276         {
7277           int pos=(int)std::distance(orderBg,where);
7278           tmp2[pos]++;
7279           tmp[std::distance(connI,i)]=pos;
7280         }
7281       else
7282         {
7283           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7284           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7285           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7286           throw INTERP_KERNEL::Exception(oss.str().c_str());
7287         }
7288     }
7289   nbPerType=tmpb.retn();
7290   return tmpa.retn();
7291 }
7292
7293 /*!
7294  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7295  *
7296  * \return a new object containing the old to new correspondance.
7297  *
7298  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7299  */
7300 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7301 {
7302   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7303 }
7304
7305 /*!
7306  * 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.
7307  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7308  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7309  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7310  */
7311 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7312 {
7313   DataArrayInt *nbPerType=0;
7314   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7315   nbPerType->decrRef();
7316   return tmpa->buildPermArrPerLevel();
7317 }
7318
7319 /*!
7320  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7321  * The number of cells remains unchanged after the call of this method.
7322  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7323  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7324  *
7325  * \return the array giving the correspondance old to new.
7326  */
7327 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7328 {
7329   checkFullyDefined();
7330   computeTypes();
7331   const int *conn=_nodal_connec->getConstPointer();
7332   const int *connI=_nodal_connec_index->getConstPointer();
7333   int nbOfCells=getNumberOfCells();
7334   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7335   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7336     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7337       {
7338         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7339         types.push_back(curType);
7340         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7341       }
7342   DataArrayInt *ret=DataArrayInt::New();
7343   ret->alloc(nbOfCells,1);
7344   int *retPtr=ret->getPointer();
7345   std::fill(retPtr,retPtr+nbOfCells,-1);
7346   int newCellId=0;
7347   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7348     {
7349       for(const int *i=connI;i!=connI+nbOfCells;i++)
7350         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7351           retPtr[std::distance(connI,i)]=newCellId++;
7352     }
7353   renumberCells(retPtr,false);
7354   return ret;
7355 }
7356
7357 /*!
7358  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7359  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7360  * This method makes asumption that connectivity is correctly set before calling.
7361  */
7362 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7363 {
7364   checkConnectivityFullyDefined();
7365   const int *conn=_nodal_connec->getConstPointer();
7366   const int *connI=_nodal_connec_index->getConstPointer();
7367   int nbOfCells=getNumberOfCells();
7368   std::vector<MEDCouplingUMesh *> ret;
7369   for(const int *i=connI;i!=connI+nbOfCells;)
7370     {
7371       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7372       int beginCellId=(int)std::distance(connI,i);
7373       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7374       int endCellId=(int)std::distance(connI,i);
7375       int sz=endCellId-beginCellId;
7376       int *cells=new int[sz];
7377       for(int j=0;j<sz;j++)
7378         cells[j]=beginCellId+j;
7379       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7380       delete [] cells;
7381       ret.push_back(m);
7382     }
7383   return ret;
7384 }
7385
7386 /*!
7387  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7388  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7389  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7390  *
7391  * \return a newly allocated instance, that the caller must manage.
7392  * \throw If \a this contains more than one geometric type.
7393  * \throw If the nodal connectivity of \a this is not fully defined.
7394  * \throw If the internal data is not coherent.
7395  */
7396 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7397 {
7398   checkConnectivityFullyDefined();
7399   if(_types.size()!=1)
7400     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7401   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7402   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7403   ret->setCoords(getCoords());
7404   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7405   if(retC)
7406     {
7407       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7408       retC->setNodalConnectivity(c);
7409     }
7410   else
7411     {
7412       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7413       if(!retD)
7414         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7415       DataArrayInt *c=0,*ci=0;
7416       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7417       MCAuto<DataArrayInt> cs(c),cis(ci);
7418       retD->setNodalConnectivity(cs,cis);
7419     }
7420   return ret.retn();
7421 }
7422
7423 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7424 {
7425   checkConnectivityFullyDefined();
7426   if(_types.size()!=1)
7427     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7428   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7429   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7430   if(cm.isDynamic())
7431     {
7432       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7433       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7434       throw INTERP_KERNEL::Exception(oss.str().c_str());
7435     }
7436   int nbCells=getNumberOfCells();
7437   int typi=(int)typ;
7438   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7439   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7440   int *outPtr=connOut->getPointer();
7441   const int *conn=_nodal_connec->begin();
7442   const int *connI=_nodal_connec_index->begin();
7443   nbNodesPerCell++;
7444   for(int i=0;i<nbCells;i++,connI++)
7445     {
7446       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7447         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7448       else
7449         {
7450           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 << ") !";
7451           throw INTERP_KERNEL::Exception(oss.str().c_str());
7452         }
7453     }
7454   return connOut.retn();
7455 }
7456
7457 /*!
7458  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7459  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7460  * \param nodalConn
7461  * \param nodalConnI
7462  */
7463 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7464 {
7465   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
7466   checkConnectivityFullyDefined();
7467   if(_types.size()!=1)
7468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7469   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7470   if(lgth<nbCells)
7471     throw INTERP_KERNEL::Exception(msg0);
7472   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7473   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7474   int *cp(c->getPointer()),*cip(ci->getPointer());
7475   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7476   cip[0]=0;
7477   for(int i=0;i<nbCells;i++,cip++,incip++)
7478     {
7479       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7480       int delta(stop-strt);
7481       if(delta>=1)
7482         {
7483           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7484             cp=std::copy(incp+strt,incp+stop,cp);
7485           else
7486             throw INTERP_KERNEL::Exception(msg0);
7487         }
7488       else
7489         throw INTERP_KERNEL::Exception(msg0);
7490       cip[1]=cip[0]+delta;
7491     }
7492   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7493 }
7494
7495 /*!
7496  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7497  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7498  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7499  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7500  * are not used here to avoid the build of big permutation array.
7501  *
7502  * \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
7503  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7504  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7505  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7506  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7507  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7508  * \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
7509  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7510  */
7511 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7512                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7513                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7514 {
7515   std::vector<const MEDCouplingUMesh *> ms2;
7516   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7517     if(*it)
7518       {
7519         (*it)->checkConnectivityFullyDefined();
7520         ms2.push_back(*it);
7521       }
7522   if(ms2.empty())
7523     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7524   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7525   int meshDim=ms2[0]->getMeshDimension();
7526   std::vector<const MEDCouplingUMesh *> m1ssm;
7527   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
7528   //
7529   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7530   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
7531   int fake=0,rk=0;
7532   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7533   ret1->alloc(0,1); ret2->alloc(0,1);
7534   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7535     {
7536       if(meshDim!=(*it)->getMeshDimension())
7537         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7538       if(refCoo!=(*it)->getCoords())
7539         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7540       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7541       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7542       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
7543       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7544         {
7545           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7546           m1ssmSingleAuto.push_back(singleCell);
7547           m1ssmSingle.push_back(singleCell);
7548           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7549         }
7550     }
7551   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7552   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7553   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7554   for(std::size_t i=0;i<m1ssm.size();i++)
7555     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7556   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7557   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7558   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7559   return ret0.retn();
7560 }
7561
7562 /*!
7563  * This method returns a newly created DataArrayInt instance.
7564  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7565  */
7566 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7567 {
7568   checkFullyDefined();
7569   const int *conn=_nodal_connec->getConstPointer();
7570   const int *connIndex=_nodal_connec_index->getConstPointer();
7571   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7572   for(const int *w=begin;w!=end;w++)
7573     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7574       ret->pushBackSilent(*w);
7575   return ret.retn();
7576 }
7577
7578 /*!
7579  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7580  * are in [0:getNumberOfCells())
7581  */
7582 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7583 {
7584   checkFullyDefined();
7585   const int *conn=_nodal_connec->getConstPointer();
7586   const int *connI=_nodal_connec_index->getConstPointer();
7587   int nbOfCells=getNumberOfCells();
7588   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7589   int *tmp=new int[nbOfCells];
7590   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7591     {
7592       int j=0;
7593       for(const int *i=connI;i!=connI+nbOfCells;i++)
7594         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7595           tmp[std::distance(connI,i)]=j++;
7596     }
7597   DataArrayInt *ret=DataArrayInt::New();
7598   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7599   ret->copyStringInfoFrom(*da);
7600   int *retPtr=ret->getPointer();
7601   const int *daPtr=da->getConstPointer();
7602   int nbOfElems=da->getNbOfElems();
7603   for(int k=0;k<nbOfElems;k++)
7604     retPtr[k]=tmp[daPtr[k]];
7605   delete [] tmp;
7606   return ret;
7607 }
7608
7609 /*!
7610  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7611  * This method \b works \b for mesh sorted by type.
7612  * cells whose ids is in 'idsPerGeoType' array.
7613  * This method conserves coords and name of mesh.
7614  */
7615 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7616 {
7617   std::vector<int> code=getDistributionOfTypes();
7618   std::size_t nOfTypesInThis=code.size()/3;
7619   int sz=0,szOfType=0;
7620   for(std::size_t i=0;i<nOfTypesInThis;i++)
7621     {
7622       if(code[3*i]!=type)
7623         sz+=code[3*i+1];
7624       else
7625         szOfType=code[3*i+1];
7626     }
7627   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7628     if(*work<0 || *work>=szOfType)
7629       {
7630         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7631         oss << ". It should be in [0," << szOfType << ") !";
7632         throw INTERP_KERNEL::Exception(oss.str().c_str());
7633       }
7634   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7635   int *idsPtr=idsTokeep->getPointer();
7636   int offset=0;
7637   for(std::size_t i=0;i<nOfTypesInThis;i++)
7638     {
7639       if(code[3*i]!=type)
7640         for(int j=0;j<code[3*i+1];j++)
7641           *idsPtr++=offset+j;
7642       else
7643         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7644       offset+=code[3*i+1];
7645     }
7646   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7647   ret->copyTinyInfoFrom(this);
7648   return ret.retn();
7649 }
7650
7651 /*!
7652  * This method returns a vector of size 'this->getNumberOfCells()'.
7653  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7654  */
7655 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7656 {
7657   int ncell=getNumberOfCells();
7658   std::vector<bool> ret(ncell);
7659   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7660   const int *c=getNodalConnectivity()->getConstPointer();
7661   for(int i=0;i<ncell;i++)
7662     {
7663       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7664       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7665       ret[i]=cm.isQuadratic();
7666     }
7667   return ret;
7668 }
7669
7670 /*!
7671  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7672  */
7673 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7674 {
7675   if(other->getType()!=UNSTRUCTURED)
7676     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7677   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7678   return MergeUMeshes(this,otherC);
7679 }
7680
7681 /*!
7682  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7683  * computed by averaging coordinates of cell nodes, so this method is not a right
7684  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7685  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7686  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7687  *          components. The caller is to delete this array using decrRef() as it is
7688  *          no more needed.
7689  *  \throw If the coordinates array is not set.
7690  *  \throw If the nodal connectivity of cells is not defined.
7691  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7692  */
7693 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
7694 {
7695   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7696   int spaceDim=getSpaceDimension();
7697   int nbOfCells=getNumberOfCells();
7698   ret->alloc(nbOfCells,spaceDim);
7699   ret->copyStringInfoFrom(*getCoords());
7700   double *ptToFill=ret->getPointer();
7701   const int *nodal=_nodal_connec->getConstPointer();
7702   const int *nodalI=_nodal_connec_index->getConstPointer();
7703   const double *coor=_coords->getConstPointer();
7704   for(int i=0;i<nbOfCells;i++)
7705     {
7706       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7707       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7708       ptToFill+=spaceDim;
7709     }
7710   return ret.retn();
7711 }
7712
7713 /*!
7714  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7715  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
7716  * 
7717  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7718  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7719  * 
7720  * \sa MEDCouplingUMesh::computeCellCenterOfMass
7721  * \throw If \a this is not fully defined (coordinates and connectivity)
7722  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7723  */
7724 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7725 {
7726   checkFullyDefined();
7727   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7728   int spaceDim=getSpaceDimension();
7729   int nbOfCells=getNumberOfCells();
7730   int nbOfNodes=getNumberOfNodes();
7731   ret->alloc(nbOfCells,spaceDim);
7732   double *ptToFill=ret->getPointer();
7733   const int *nodal=_nodal_connec->getConstPointer();
7734   const int *nodalI=_nodal_connec_index->getConstPointer();
7735   const double *coor=_coords->getConstPointer();
7736   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7737     {
7738       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7739       std::fill(ptToFill,ptToFill+spaceDim,0.);
7740       if(type!=INTERP_KERNEL::NORM_POLYHED)
7741         {
7742           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7743             {
7744               if(*conn>=0 && *conn<nbOfNodes)
7745                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7746               else
7747                 {
7748                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7749                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7750                 }
7751             }
7752           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7753           if(nbOfNodesInCell>0)
7754             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7755           else
7756             {
7757               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7758               throw INTERP_KERNEL::Exception(oss.str().c_str());
7759             }
7760         }
7761       else
7762         {
7763           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7764           s.erase(-1);
7765           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7766             {
7767               if(*it>=0 && *it<nbOfNodes)
7768                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7769               else
7770                 {
7771                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7772                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7773                 }
7774             }
7775           if(!s.empty())
7776             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7777           else
7778             {
7779               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7780               throw INTERP_KERNEL::Exception(oss.str().c_str());
7781             }
7782         }
7783     }
7784   return ret.retn();
7785 }
7786
7787 /*!
7788  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7789  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7790  * are specified via an array of cell ids. 
7791  *  \warning Validity of the specified cell ids is not checked! 
7792  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7793  *  \param [in] begin - an array of cell ids of interest.
7794  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7795  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7796  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7797  *          caller is to delete this array using decrRef() as it is no more needed. 
7798  *  \throw If the coordinates array is not set.
7799  *  \throw If the nodal connectivity of cells is not defined.
7800  *
7801  *  \if ENABLE_EXAMPLES
7802  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7803  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7804  *  \endif
7805  */
7806 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7807 {
7808   DataArrayDouble *ret=DataArrayDouble::New();
7809   int spaceDim=getSpaceDimension();
7810   int nbOfTuple=(int)std::distance(begin,end);
7811   ret->alloc(nbOfTuple,spaceDim);
7812   double *ptToFill=ret->getPointer();
7813   double *tmp=new double[spaceDim];
7814   const int *nodal=_nodal_connec->getConstPointer();
7815   const int *nodalI=_nodal_connec_index->getConstPointer();
7816   const double *coor=_coords->getConstPointer();
7817   for(const int *w=begin;w!=end;w++)
7818     {
7819       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7820       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7821       ptToFill+=spaceDim;
7822     }
7823   delete [] tmp;
7824   return ret;
7825 }
7826
7827 /*!
7828  * 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".
7829  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7830  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7831  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7832  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7833  * 
7834  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7835  * \throw If spaceDim!=3 or meshDim!=2.
7836  * \throw If connectivity of \a this is invalid.
7837  * \throw If connectivity of a cell in \a this points to an invalid node.
7838  */
7839 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7840 {
7841   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
7842   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7843   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7844     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7845   ret->alloc(nbOfCells,4);
7846   double *retPtr(ret->getPointer());
7847   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7848   const double *coor(_coords->begin());
7849   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7850     {
7851       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7852       if(nodalI[1]-nodalI[0]>=3)
7853         {
7854           for(int j=0;j<3;j++)
7855             {
7856               int nodeId(nodal[nodalI[0]+1+j]);
7857               if(nodeId>=0 && nodeId<nbOfNodes)
7858                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7859               else
7860                 {
7861                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7862                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7863                 }
7864             }
7865         }
7866       else
7867         {
7868           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7869           throw INTERP_KERNEL::Exception(oss.str().c_str());
7870         }
7871       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7872       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7873     }
7874   return ret.retn();
7875 }
7876
7877 /*!
7878  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7879  * 
7880  */
7881 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7882 {
7883   if(!da)
7884     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7885   da->checkAllocated();
7886   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7887   ret->setCoords(da);
7888   int nbOfTuples=da->getNumberOfTuples();
7889   MCAuto<DataArrayInt> c=DataArrayInt::New();
7890   MCAuto<DataArrayInt> cI=DataArrayInt::New();
7891   c->alloc(2*nbOfTuples,1);
7892   cI->alloc(nbOfTuples+1,1);
7893   int *cp=c->getPointer();
7894   int *cip=cI->getPointer();
7895   *cip++=0;
7896   for(int i=0;i<nbOfTuples;i++)
7897     {
7898       *cp++=INTERP_KERNEL::NORM_POINT1;
7899       *cp++=i;
7900       *cip++=2*(i+1);
7901     }
7902   ret->setConnectivity(c,cI,true);
7903   return ret.retn();
7904 }
7905 /*!
7906  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7907  * Cells and nodes of
7908  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7909  *  \param [in] mesh1 - the first mesh.
7910  *  \param [in] mesh2 - the second mesh.
7911  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7912  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7913  *          is no more needed.
7914  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7915  *  \throw If the coordinates array is not set in none of the meshes.
7916  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7917  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7918  */
7919 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7920 {
7921   std::vector<const MEDCouplingUMesh *> tmp(2);
7922   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7923   return MergeUMeshes(tmp);
7924 }
7925
7926 /*!
7927  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7928  * Cells and nodes of
7929  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7930  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7931  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7932  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7933  *          is no more needed.
7934  *  \throw If \a a.size() == 0.
7935  *  \throw If \a a[ *i* ] == NULL.
7936  *  \throw If the coordinates array is not set in none of the meshes.
7937  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7938  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7939  */
7940 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7941 {
7942   std::size_t sz=a.size();
7943   if(sz==0)
7944     return MergeUMeshesLL(a);
7945   for(std::size_t ii=0;ii<sz;ii++)
7946     if(!a[ii])
7947       {
7948         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7949         throw INTERP_KERNEL::Exception(oss.str().c_str());
7950       }
7951   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
7952   std::vector< const MEDCouplingUMesh * > aa(sz);
7953   int spaceDim=-3;
7954   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7955     {
7956       const MEDCouplingUMesh *cur=a[i];
7957       const DataArrayDouble *coo=cur->getCoords();
7958       if(coo)
7959         spaceDim=coo->getNumberOfComponents();
7960     }
7961   if(spaceDim==-3)
7962     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7963   for(std::size_t i=0;i<sz;i++)
7964     {
7965       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7966       aa[i]=bb[i];
7967     }
7968   return MergeUMeshesLL(aa);
7969 }
7970
7971 /// @cond INTERNAL
7972
7973 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7974 {
7975   if(a.empty())
7976     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7977   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7978   int meshDim=(*it)->getMeshDimension();
7979   int nbOfCells=(*it)->getNumberOfCells();
7980   int meshLgth=(*it++)->getNodalConnectivityArrayLen();
7981   for(;it!=a.end();it++)
7982     {
7983       if(meshDim!=(*it)->getMeshDimension())
7984         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7985       nbOfCells+=(*it)->getNumberOfCells();
7986       meshLgth+=(*it)->getNodalConnectivityArrayLen();
7987     }
7988   std::vector<const MEDCouplingPointSet *> aps(a.size());
7989   std::copy(a.begin(),a.end(),aps.begin());
7990   MCAuto<DataArrayDouble> pts=MergeNodesArray(aps);
7991   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7992   ret->setCoords(pts);
7993   MCAuto<DataArrayInt> c=DataArrayInt::New();
7994   c->alloc(meshLgth,1);
7995   int *cPtr=c->getPointer();
7996   MCAuto<DataArrayInt> cI=DataArrayInt::New();
7997   cI->alloc(nbOfCells+1,1);
7998   int *cIPtr=cI->getPointer();
7999   *cIPtr++=0;
8000   int offset=0;
8001   int offset2=0;
8002   for(it=a.begin();it!=a.end();it++)
8003     {
8004       int curNbOfCell=(*it)->getNumberOfCells();
8005       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
8006       const int *curC=(*it)->_nodal_connec->getConstPointer();
8007       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
8008       for(int j=0;j<curNbOfCell;j++)
8009         {
8010           const int *src=curC+curCI[j];
8011           *cPtr++=*src++;
8012           for(;src!=curC+curCI[j+1];src++,cPtr++)
8013             {
8014               if(*src!=-1)
8015                 *cPtr=*src+offset2;
8016               else
8017                 *cPtr=-1;
8018             }
8019         }
8020       offset+=curCI[curNbOfCell];
8021       offset2+=(*it)->getNumberOfNodes();
8022     }
8023   //
8024   ret->setConnectivity(c,cI,true);
8025   return ret.retn();
8026 }
8027
8028 /// @endcond
8029
8030 /*!
8031  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
8032  * dimension and sharing the node coordinates array.
8033  * All cells of the first mesh precede all cells of the second mesh
8034  * within the result mesh. 
8035  *  \param [in] mesh1 - the first mesh.
8036  *  \param [in] mesh2 - the second mesh.
8037  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8038  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8039  *          is no more needed.
8040  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
8041  *  \throw If the meshes do not share the node coordinates array.
8042  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
8043  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
8044  */
8045 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
8046 {
8047   std::vector<const MEDCouplingUMesh *> tmp(2);
8048   tmp[0]=mesh1; tmp[1]=mesh2;
8049   return MergeUMeshesOnSameCoords(tmp);
8050 }
8051
8052 /*!
8053  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8054  * dimension and sharing the node coordinates array.
8055  * All cells of the *i*-th mesh precede all cells of the
8056  * (*i*+1)-th mesh within the result mesh.
8057  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8058  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8059  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8060  *          is no more needed.
8061  *  \throw If \a a.size() == 0.
8062  *  \throw If \a a[ *i* ] == NULL.
8063  *  \throw If the meshes do not share the node coordinates array.
8064  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
8065  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
8066  */
8067 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
8068 {
8069   if(meshes.empty())
8070     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
8071   for(std::size_t ii=0;ii<meshes.size();ii++)
8072     if(!meshes[ii])
8073       {
8074         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
8075         throw INTERP_KERNEL::Exception(oss.str().c_str());
8076       }
8077   const DataArrayDouble *coords=meshes.front()->getCoords();
8078   int meshDim=meshes.front()->getMeshDimension();
8079   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
8080   int meshLgth=0;
8081   int meshIndexLgth=0;
8082   for(;iter!=meshes.end();iter++)
8083     {
8084       if(coords!=(*iter)->getCoords())
8085         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8086       if(meshDim!=(*iter)->getMeshDimension())
8087         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8088       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
8089       meshIndexLgth+=(*iter)->getNumberOfCells();
8090     }
8091   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
8092   nodal->alloc(meshLgth,1);
8093   int *nodalPtr=nodal->getPointer();
8094   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
8095   nodalIndex->alloc(meshIndexLgth+1,1);
8096   int *nodalIndexPtr=nodalIndex->getPointer();
8097   int offset=0;
8098   for(iter=meshes.begin();iter!=meshes.end();iter++)
8099     {
8100       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8101       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8102       int nbOfCells=(*iter)->getNumberOfCells();
8103       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
8104       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8105       if(iter!=meshes.begin())
8106         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8107       else
8108         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8109       offset+=meshLgth2;
8110     }
8111   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8112   ret->setName("merge");
8113   ret->setMeshDimension(meshDim);
8114   ret->setConnectivity(nodal,nodalIndex,true);
8115   ret->setCoords(coords);
8116   return ret;
8117 }
8118
8119 /*!
8120  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8121  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8122  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8123  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8124  * New" mode are returned for each input mesh.
8125  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8126  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8127  *          valid values [0,1,2], see zipConnectivityTraducer().
8128  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8129  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8130  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8131  *          no more needed.
8132  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8133  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8134  *          is no more needed.
8135  *  \throw If \a meshes.size() == 0.
8136  *  \throw If \a meshes[ *i* ] == NULL.
8137  *  \throw If the meshes do not share the node coordinates array.
8138  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8139  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8140  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8141  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8142  */
8143 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8144 {
8145   //All checks are delegated to MergeUMeshesOnSameCoords
8146   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8147   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8148   corr.resize(meshes.size());
8149   std::size_t nbOfMeshes=meshes.size();
8150   int offset=0;
8151   const int *o2nPtr=o2n->getConstPointer();
8152   for(std::size_t i=0;i<nbOfMeshes;i++)
8153     {
8154       DataArrayInt *tmp=DataArrayInt::New();
8155       int curNbOfCells=meshes[i]->getNumberOfCells();
8156       tmp->alloc(curNbOfCells,1);
8157       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8158       offset+=curNbOfCells;
8159       tmp->setName(meshes[i]->getName());
8160       corr[i]=tmp;
8161     }
8162   return ret.retn();
8163 }
8164
8165 /*!
8166  * Makes all given meshes share the nodal connectivity array. The common connectivity
8167  * array is created by concatenating the connectivity arrays of all given meshes. All
8168  * the given meshes must be of the same space dimension but dimension of cells **can
8169  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8170  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8171  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8172  *  \param [in,out] meshes - a vector of meshes to update.
8173  *  \throw If any of \a meshes is NULL.
8174  *  \throw If the coordinates array is not set in any of \a meshes.
8175  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8176  *  \throw If \a meshes are of different space dimension.
8177  */
8178 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8179 {
8180   std::size_t sz=meshes.size();
8181   if(sz==0 || sz==1)
8182     return;
8183   std::vector< const DataArrayDouble * > coords(meshes.size());
8184   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8185   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8186     {
8187       if((*it))
8188         {
8189           (*it)->checkConnectivityFullyDefined();
8190           const DataArrayDouble *coo=(*it)->getCoords();
8191           if(coo)
8192             *it2=coo;
8193           else
8194             {
8195               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8196               oss << " has no coordinate array defined !";
8197               throw INTERP_KERNEL::Exception(oss.str().c_str());
8198             }
8199         }
8200       else
8201         {
8202           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8203           oss << " is null !";
8204           throw INTERP_KERNEL::Exception(oss.str().c_str());
8205         }
8206     }
8207   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8208   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8209   int offset=(*it)->getNumberOfNodes();
8210   (*it++)->setCoords(res);
8211   for(;it!=meshes.end();it++)
8212     {
8213       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8214       (*it)->setCoords(res);
8215       (*it)->shiftNodeNumbersInConn(offset);
8216       offset+=oldNumberOfNodes;
8217     }
8218 }
8219
8220 /*!
8221  * Merges nodes coincident with a given precision within all given meshes that share
8222  * the nodal connectivity array. The given meshes **can be of different** mesh
8223  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8224  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8225  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8226  *  \param [in,out] meshes - a vector of meshes to update.
8227  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8228  *  \throw If any of \a meshes is NULL.
8229  *  \throw If the \a meshes do not share the same node coordinates array.
8230  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8231  */
8232 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8233 {
8234   if(meshes.empty())
8235     return ;
8236   std::set<const DataArrayDouble *> s;
8237   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8238     {
8239       if(*it)
8240         s.insert((*it)->getCoords());
8241       else
8242         {
8243           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 !";
8244           throw INTERP_KERNEL::Exception(oss.str().c_str());
8245         }
8246     }
8247   if(s.size()!=1)
8248     {
8249       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 !";
8250       throw INTERP_KERNEL::Exception(oss.str().c_str());
8251     }
8252   const DataArrayDouble *coo=*(s.begin());
8253   if(!coo)
8254     return;
8255   //
8256   DataArrayInt *comm,*commI;
8257   coo->findCommonTuples(eps,-1,comm,commI);
8258   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
8259   int oldNbOfNodes=coo->getNumberOfTuples();
8260   int newNbOfNodes;
8261   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8262   if(oldNbOfNodes==newNbOfNodes)
8263     return ;
8264   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8265   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8266     {
8267       (*it)->renumberNodesInConn(o2n->getConstPointer());
8268       (*it)->setCoords(newCoords);
8269     } 
8270 }
8271
8272 /*!
8273  * 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.
8274  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8275  * \param isQuad specifies the policy of connectivity.
8276  * @ret in/out parameter in which the result will be append
8277  */
8278 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8279 {
8280   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8281   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8282   ret.push_back(cm.getExtrudedType());
8283   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8284   switch(flatType)
8285   {
8286     case INTERP_KERNEL::NORM_POINT1:
8287       {
8288         ret.push_back(connBg[1]);
8289         ret.push_back(connBg[1]+nbOfNodesPerLev);
8290         break;
8291       }
8292     case INTERP_KERNEL::NORM_SEG2:
8293       {
8294         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8295         ret.insert(ret.end(),conn,conn+4);
8296         break;
8297       }
8298     case INTERP_KERNEL::NORM_SEG3:
8299       {
8300         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8301         ret.insert(ret.end(),conn,conn+8);
8302         break;
8303       }
8304     case INTERP_KERNEL::NORM_QUAD4:
8305       {
8306         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8307         ret.insert(ret.end(),conn,conn+8);
8308         break;
8309       }
8310     case INTERP_KERNEL::NORM_TRI3:
8311       {
8312         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8313         ret.insert(ret.end(),conn,conn+6);
8314         break;
8315       }
8316     case INTERP_KERNEL::NORM_TRI6:
8317       {
8318         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,
8319           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8320         ret.insert(ret.end(),conn,conn+15);
8321         break;
8322       }
8323     case INTERP_KERNEL::NORM_QUAD8:
8324       {
8325         int conn[20]={
8326           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8327           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8328           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8329         };
8330         ret.insert(ret.end(),conn,conn+20);
8331         break;
8332       }
8333     case INTERP_KERNEL::NORM_POLYGON:
8334       {
8335         std::back_insert_iterator< std::vector<int> > ii(ret);
8336         std::copy(connBg+1,connEnd,ii);
8337         *ii++=-1;
8338         std::reverse_iterator<const int *> rConnBg(connEnd);
8339         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8340         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8341         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8342         for(std::size_t i=0;i<nbOfRadFaces;i++)
8343           {
8344             *ii++=-1;
8345             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8346             std::copy(conn,conn+4,ii);
8347           }
8348         break;
8349       }
8350     default:
8351       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8352   }
8353 }
8354
8355 /*!
8356  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8357  */
8358 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8359 {
8360   std::size_t i, ip1;
8361   double v[3]={0.,0.,0.};
8362   std::size_t sz=std::distance(begin,end);
8363   if(isQuadratic)
8364     sz/=2;
8365   for(i=0;i<sz;i++)
8366     {
8367       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];
8368       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8369       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8370     }
8371   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8372
8373   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8374   // SEG3 forming a circle):
8375   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8376     {
8377       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8378       for(std::size_t j=0;j<sz;j++)
8379         {
8380           if (j%2)  // current point i is quadratic, next point i+1 is standard
8381             {
8382               i = sz+j;
8383               ip1 = (j+1)%sz; // ip1 = "i+1"
8384             }
8385           else      // current point i is standard, next point i+1 is quadratic
8386             {
8387               i = j;
8388               ip1 = j+sz;
8389             }
8390           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8391           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8392           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8393         }
8394       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8395     }
8396   return (ret>0.);
8397 }
8398
8399 /*!
8400  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8401  */
8402 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8403 {
8404   std::vector<std::pair<int,int> > edges;
8405   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8406   const int *bgFace=begin;
8407   for(std::size_t i=0;i<nbOfFaces;i++)
8408     {
8409       const int *endFace=std::find(bgFace+1,end,-1);
8410       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8411       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8412         {
8413           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8414           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8415             return false;
8416           edges.push_back(p1);
8417         }
8418       bgFace=endFace+1;
8419     }
8420   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8421 }
8422
8423 /*!
8424  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8425  */
8426 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8427 {
8428   double vec0[3],vec1[3];
8429   std::size_t sz=std::distance(begin,end);
8430   if(sz%2!=0)
8431     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8432   int nbOfNodes=(int)sz/2;
8433   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8434   const double *pt0=coords+3*begin[0];
8435   const double *pt1=coords+3*begin[nbOfNodes];
8436   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8437   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8438 }
8439
8440 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8441 {
8442   std::size_t sz=std::distance(begin,end);
8443   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8444   std::size_t nbOfNodes(sz/2);
8445   std::copy(begin,end,(int *)tmp);
8446   for(std::size_t j=1;j<nbOfNodes;j++)
8447     {
8448       begin[j]=tmp[nbOfNodes-j];
8449       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8450     }
8451 }
8452
8453 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8454 {
8455   std::size_t sz=std::distance(begin,end);
8456   if(sz!=4)
8457     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
8458   double vec0[3],vec1[3];
8459   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8460   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]; 
8461   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;
8462 }
8463
8464 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8465 {
8466   std::size_t sz=std::distance(begin,end);
8467   if(sz!=5)
8468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
8469   double vec0[3];
8470   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8471   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8472   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8473 }
8474
8475 /*!
8476  * 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 ) 
8477  * 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
8478  * a 2D space.
8479  *
8480  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8481  * \param [in] coords the coordinates with nb of components exactly equal to 3
8482  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8483  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8484  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8485  */
8486 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8487 {
8488   int nbFaces=std::count(begin+1,end,-1)+1;
8489   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8490   double *vPtr=v->getPointer();
8491   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8492   double *pPtr=p->getPointer();
8493   const int *stFaceConn=begin+1;
8494   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8495     {
8496       const int *endFaceConn=std::find(stFaceConn,end,-1);
8497       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8498       stFaceConn=endFaceConn+1;
8499     }
8500   pPtr=p->getPointer(); vPtr=v->getPointer();
8501   DataArrayInt *comm1=0,*commI1=0;
8502   v->findCommonTuples(eps,-1,comm1,commI1);
8503   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8504   const int *comm1Ptr=comm1->getConstPointer();
8505   const int *commI1Ptr=commI1->getConstPointer();
8506   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8507   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8508   //
8509   MCAuto<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8510   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8511   mm->finishInsertingCells();
8512   //
8513   for(int i=0;i<nbOfGrps1;i++)
8514     {
8515       int vecId=comm1Ptr[commI1Ptr[i]];
8516       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8517       DataArrayInt *comm2=0,*commI2=0;
8518       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8519       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8520       const int *comm2Ptr=comm2->getConstPointer();
8521       const int *commI2Ptr=commI2->getConstPointer();
8522       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8523       for(int j=0;j<nbOfGrps2;j++)
8524         {
8525           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8526             {
8527               res->insertAtTheEnd(begin,end);
8528               res->pushBackSilent(-1);
8529             }
8530           else
8531             {
8532               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8533               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
8534               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8535               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8536               MCAuto<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8537               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8538               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8539               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8540               const int *idsNodePtr=idsNode->getConstPointer();
8541               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];
8542               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8543               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8544               if(std::abs(norm)>eps)
8545                 {
8546                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8547                   mm3->rotate(center,vec,angle);
8548                 }
8549               mm3->changeSpaceDimension(2);
8550               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8551               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8552               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8553               int nbOfCells=mm4->getNumberOfCells();
8554               for(int k=0;k<nbOfCells;k++)
8555                 {
8556                   int l=0;
8557                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8558                     res->pushBackSilent(idsNodePtr[*work]);
8559                   res->pushBackSilent(-1);
8560                 }
8561             }
8562         }
8563     }
8564   res->popBackSilent();
8565 }
8566
8567 /*!
8568  * 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
8569  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8570  * 
8571  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8572  * \param [in] coords coordinates expected to have 3 components.
8573  * \param [in] begin start of the nodal connectivity of the face.
8574  * \param [in] end end of the nodal connectivity (excluded) of the face.
8575  * \param [out] v the normalized vector of size 3
8576  * \param [out] p the pos of plane
8577  */
8578 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8579 {
8580   std::size_t nbPoints=std::distance(begin,end);
8581   if(nbPoints<3)
8582     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8583   double vec[3]={0.,0.,0.};
8584   std::size_t j=0;
8585   bool refFound=false;
8586   for(;j<nbPoints-1 && !refFound;j++)
8587     {
8588       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8589       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8590       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8591       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8592       if(norm>eps)
8593         {
8594           refFound=true;
8595           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8596         }
8597     }
8598   for(std::size_t i=j;i<nbPoints-1;i++)
8599     {
8600       double curVec[3];
8601       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8602       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8603       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8604       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8605       if(norm<eps)
8606         continue;
8607       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8608       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];
8609       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8610       if(norm>eps)
8611         {
8612           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8613           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8614           return ;
8615         }
8616     }
8617   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8618 }
8619
8620 /*!
8621  * This method tries to obtain a well oriented polyhedron.
8622  * If the algorithm fails, an exception will be thrown.
8623  */
8624 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8625 {
8626   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8627   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8628   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8629   isPerm[0]=true;
8630   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8631   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8632   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8633   //
8634   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8635     {
8636       bgFace=begin;
8637       std::size_t smthChanged=0;
8638       for(std::size_t i=0;i<nbOfFaces;i++)
8639         {
8640           endFace=std::find(bgFace+1,end,-1);
8641           nbOfEdgesInFace=std::distance(bgFace,endFace);
8642           if(!isPerm[i])
8643             {
8644               bool b;
8645               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8646                 {
8647                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8648                   std::pair<int,int> p2(p1.second,p1.first);
8649                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8650                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8651                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8652                 }
8653               if(isPerm[i])
8654                 { 
8655                   if(!b)
8656                     std::reverse(bgFace+1,endFace);
8657                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8658                     {
8659                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8660                       std::pair<int,int> p2(p1.second,p1.first);
8661                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8662                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8663                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8664                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8665                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8666                       if(it!=edgesOK.end())
8667                         {
8668                           edgesOK.erase(it);
8669                           edgesFinished.push_back(p1);
8670                         }
8671                       else
8672                         edgesOK.push_back(p1);
8673                     }
8674                 }
8675             }
8676           bgFace=endFace+1;
8677         }
8678       if(smthChanged==0)
8679         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8680     }
8681   if(!edgesOK.empty())
8682     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8683   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8684     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8685       bgFace=begin;
8686       for(std::size_t i=0;i<nbOfFaces;i++)
8687         {
8688           endFace=std::find(bgFace+1,end,-1);
8689           std::reverse(bgFace+1,endFace);
8690           bgFace=endFace+1;
8691         }
8692     }
8693 }
8694
8695 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8696 {
8697   int nbOfNodesExpected(skin->getNumberOfNodes());
8698   const int *n2oPtr(n2o->getConstPointer());
8699   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8700   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8701   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8702   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8703   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8704   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8705   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8706   if(nbOfNodesExpected<1)
8707     return ret.retn();
8708   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8709   *work++=n2oPtr[prevNode];
8710   for(int i=1;i<nbOfNodesExpected;i++)
8711     {
8712       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8713         {
8714           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8715           conn.erase(prevNode);
8716           if(conn.size()==1)
8717             {
8718               int curNode(*(conn.begin()));
8719               *work++=n2oPtr[curNode];
8720               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8721               shar.erase(prevCell);
8722               if(shar.size()==1)
8723                 {
8724                   prevCell=*(shar.begin());
8725                   prevNode=curNode;
8726                 }
8727               else
8728                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8729             }
8730           else
8731             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8732         }
8733       else
8734         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8735     }
8736   return ret.retn();
8737 }
8738
8739 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8740 {
8741   int nbOfNodesExpected(skin->getNumberOfNodes());
8742   int nbOfTurn(nbOfNodesExpected/2);
8743   const int *n2oPtr(n2o->getConstPointer());
8744   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8745   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8746   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8747   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8748   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8749   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8750   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8751   if(nbOfNodesExpected<1)
8752     return ret.retn();
8753   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8754   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8755   for(int i=1;i<nbOfTurn;i++)
8756     {
8757       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8758         {
8759           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8760           conn.erase(prevNode);
8761           if(conn.size()==1)
8762             {
8763               int curNode(*(conn.begin()));
8764               *work=n2oPtr[curNode];
8765               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8766               shar.erase(prevCell);
8767               if(shar.size()==1)
8768                 {
8769                   int curCell(*(shar.begin()));
8770                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8771                   prevCell=curCell;
8772                   prevNode=curNode;
8773                   work++;
8774                 }
8775               else
8776                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8777             }
8778           else
8779             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8780         }
8781       else
8782         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8783     }
8784   return ret.retn();
8785 }
8786
8787 /*!
8788  * This method makes the assumption spacedimension == meshdimension == 2.
8789  * This method works only for linear cells.
8790  * 
8791  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8792  */
8793 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8794 {
8795   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8796     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8797   MCAuto<MEDCouplingUMesh> skin(computeSkin());
8798   int oldNbOfNodes(skin->getNumberOfNodes());
8799   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
8800   int nbOfNodesExpected(skin->getNumberOfNodes());
8801   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8802   int nbCells(skin->getNumberOfCells());
8803   if(nbCells==nbOfNodesExpected)
8804     return buildUnionOf2DMeshLinear(skin,n2o);
8805   else if(2*nbCells==nbOfNodesExpected)
8806     return buildUnionOf2DMeshQuadratic(skin,n2o);
8807   else
8808     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8809 }
8810
8811 /*!
8812  * This method makes the assumption spacedimension == meshdimension == 3.
8813  * This method works only for linear cells.
8814  * 
8815  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8816  */
8817 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8818 {
8819   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8820     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8821   MCAuto<MEDCouplingUMesh> m=computeSkin();
8822   const int *conn=m->getNodalConnectivity()->getConstPointer();
8823   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8824   int nbOfCells=m->getNumberOfCells();
8825   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8826   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8827   if(nbOfCells<1)
8828     return ret.retn();
8829   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8830   for(int i=1;i<nbOfCells;i++)
8831     {
8832       *work++=-1;
8833       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8834     }
8835   return ret.retn();
8836 }
8837
8838 /*!
8839  * \brief Creates a graph of cell neighbors
8840  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8841  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8842  *  For example
8843  *  - index:  0 3 5 6 6
8844  *  - value:  1 2 3 2 3 3
8845  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8846  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8847  */
8848 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8849 {
8850   checkConnectivityFullyDefined();
8851
8852   int meshDim = this->getMeshDimension();
8853   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
8854   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
8855   this->getReverseNodalConnectivity(revConn,indexr);
8856   const int* indexr_ptr=indexr->getConstPointer();
8857   const int* revConn_ptr=revConn->getConstPointer();
8858
8859   const MEDCoupling::DataArrayInt* index;
8860   const MEDCoupling::DataArrayInt* conn;
8861   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8862   index=this->getNodalConnectivityIndex();
8863   int nbCells=this->getNumberOfCells();
8864   const int* index_ptr=index->getConstPointer();
8865   const int* conn_ptr=conn->getConstPointer();
8866
8867   //creating graph arcs (cell to cell relations)
8868   //arcs are stored in terms of (index,value) notation
8869   // 0 3 5 6 6
8870   // 1 2 3 2 3 3
8871   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8872   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8873
8874   //warning here one node have less than or equal effective number of cell with it
8875   //but cell could have more than effective nodes
8876   //because other equals nodes in other domain (with other global inode)
8877   std::vector <int> cell2cell_index(nbCells+1,0);
8878   std::vector <int> cell2cell;
8879   cell2cell.reserve(3*nbCells);
8880
8881   for (int icell=0; icell<nbCells;icell++)
8882     {
8883       std::map<int,int > counter;
8884       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8885         {
8886           int inode=conn_ptr[iconn];
8887           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8888             {
8889               int icell2=revConn_ptr[iconnr];
8890               std::map<int,int>::iterator iter=counter.find(icell2);
8891               if (iter!=counter.end()) (iter->second)++;
8892               else counter.insert(std::make_pair(icell2,1));
8893             }
8894         }
8895       for (std::map<int,int>::const_iterator iter=counter.begin();
8896            iter!=counter.end(); iter++)
8897         if (iter->second >= meshDim)
8898           {
8899             cell2cell_index[icell+1]++;
8900             cell2cell.push_back(iter->first);
8901           }
8902     }
8903   indexr->decrRef();
8904   revConn->decrRef();
8905   cell2cell_index[0]=0;
8906   for (int icell=0; icell<nbCells;icell++)
8907     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8908
8909   //filling up index and value to create skylinearray structure
8910   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8911   return array;
8912 }
8913
8914 /*!
8915  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8916  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8917  */
8918 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8919 {
8920   double *w=zipFrmt;
8921   if(spaceDim==3)
8922     for(int i=0;i<nbOfNodesInCell;i++)
8923       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8924   else if(spaceDim==2)
8925     {
8926       for(int i=0;i<nbOfNodesInCell;i++)
8927         {
8928           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8929           *w++=0.;
8930         }
8931     }
8932   else
8933     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8934 }
8935
8936 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8937 {
8938   int nbOfCells=getNumberOfCells();
8939   if(nbOfCells<=0)
8940     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8941   ofs << "  <" << getVTKDataSetType() << ">\n";
8942   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8943   ofs << "      <PointData>\n" << pointData << std::endl;
8944   ofs << "      </PointData>\n";
8945   ofs << "      <CellData>\n" << cellData << std::endl;
8946   ofs << "      </CellData>\n";
8947   ofs << "      <Points>\n";
8948   if(getSpaceDimension()==3)
8949     _coords->writeVTK(ofs,8,"Points",byteData);
8950   else
8951     {
8952       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8953       coo->writeVTK(ofs,8,"Points",byteData);
8954     }
8955   ofs << "      </Points>\n";
8956   ofs << "      <Cells>\n";
8957   const int *cPtr=_nodal_connec->getConstPointer();
8958   const int *cIPtr=_nodal_connec_index->getConstPointer();
8959   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8960   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8961   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8962   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8963   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8964   int szFaceOffsets=0,szConn=0;
8965   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8966     {
8967       *w2=cPtr[cIPtr[i]];
8968       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8969         {
8970           *w1=-1;
8971           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8972           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8973         }
8974       else
8975         {
8976           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8977           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8978           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8979           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8980           w4=std::copy(c.begin(),c.end(),w4);
8981         }
8982     }
8983   types->transformWithIndArr(MEDCOUPLING2VTKTYPETRADUCER,MEDCOUPLING2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8984   types->writeVTK(ofs,8,"UInt8","types",byteData);
8985   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8986   if(szFaceOffsets!=0)
8987     {//presence of Polyhedra
8988       connectivity->reAlloc(szConn);
8989       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8990       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8991       w1=faces->getPointer();
8992       for(int i=0;i<nbOfCells;i++)
8993         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8994           {
8995             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8996             *w1++=nbFaces;
8997             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8998             for(int j=0;j<nbFaces;j++)
8999               {
9000                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
9001                 *w1++=(int)std::distance(w6,w5);
9002                 w1=std::copy(w6,w5,w1);
9003                 w6=w5+1;
9004               }
9005           }
9006       faces->writeVTK(ofs,8,"Int32","faces",byteData);
9007     }
9008   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
9009   ofs << "      </Cells>\n";
9010   ofs << "    </Piece>\n";
9011   ofs << "  </" << getVTKDataSetType() << ">\n";
9012 }
9013
9014 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
9015 {
9016   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
9017   if(_mesh_dim==-2)
9018     { stream << " Not set !"; return ; }
9019   stream << " Mesh dimension : " << _mesh_dim << ".";
9020   if(_mesh_dim==-1)
9021     return ;
9022   if(!_coords)
9023     { stream << " No coordinates set !"; return ; }
9024   if(!_coords->isAllocated())
9025     { stream << " Coordinates set but not allocated !"; return ; }
9026   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
9027   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
9028   if(!_nodal_connec_index)
9029     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
9030   if(!_nodal_connec_index->isAllocated())
9031     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
9032   int lgth=_nodal_connec_index->getNumberOfTuples();
9033   int cpt=_nodal_connec_index->getNumberOfComponents();
9034   if(cpt!=1 || lgth<1)
9035     return ;
9036   stream << std::endl << "Number of cells : " << lgth-1 << ".";
9037 }
9038
9039 std::string MEDCouplingUMesh::getVTKDataSetType() const
9040 {
9041   return std::string("UnstructuredGrid");
9042 }
9043
9044 std::string MEDCouplingUMesh::getVTKFileExtension() const
9045 {
9046   return std::string("vtu");
9047 }
9048
9049 /*!
9050  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
9051  * returns a result mesh constituted by polygons.
9052  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
9053  * all nodes from m2.
9054  * The meshes should be in 2D space. In
9055  * addition, returns two arrays mapping cells of the result mesh to cells of the input
9056  * meshes.
9057  *  \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
9058  *                      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)
9059  *  \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
9060  *                      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)
9061  *  \param [in] eps - precision used to detect coincident mesh entities.
9062  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
9063  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
9064  *         this array using decrRef() as it is no more needed.
9065  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
9066  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
9067  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
9068  *         any cell of \a m2. The caller is to delete this array using decrRef() as
9069  *         it is no more needed.  
9070  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
9071  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
9072  *         is no more needed.  
9073  *  \throw If the coordinates array is not set in any of the meshes.
9074  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
9075  *  \throw If any of the meshes is not a 2D mesh in 2D space.
9076  *
9077  *  \sa conformize2D, mergeNodes
9078  */
9079 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9080                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9081 {
9082   if(!m1 || !m2)
9083     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9084   m1->checkFullyDefined();
9085   m2->checkFullyDefined();
9086   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9087     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
9088
9089   // Step 1: compute all edge intersections (new nodes)
9090   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9091   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9092   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9093   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9094   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9095                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9096                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9097   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9098   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9099   MCAuto<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9100
9101   // Step 2: re-order newly created nodes according to the ordering found in m2
9102   std::vector< std::vector<int> > intersectEdge2;
9103   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9104   subDiv2.clear(); dd5=0; dd6=0;
9105
9106   // Step 3:
9107   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9108   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9109   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9110                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9111
9112   // Step 4: Prepare final result:
9113   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
9114   addCooDa->alloc((int)(addCoo.size())/2,2);
9115   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9116   MCAuto<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9117   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9118   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9119   std::vector<const DataArrayDouble *> coordss(4);
9120   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9121   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9122   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9123   MCAuto<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9124   MCAuto<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9125   MCAuto<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9126   MCAuto<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9127   ret->setConnectivity(conn,connI,true);
9128   ret->setCoords(coo);
9129   cellNb1=c1.retn(); cellNb2=c2.retn();
9130   return ret.retn();
9131 }
9132
9133 /// @cond INTERNAL
9134
9135 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9136 {
9137   if(candidates.empty())
9138     return false;
9139   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9140     {
9141       const std::vector<int>& pool(intersectEdge1[*it]);
9142       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9143       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9144         {
9145           retVal=*it+1;
9146           return true;
9147         }
9148       tmp[0]=stop; tmp[1]=start;
9149       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9150         {
9151           retVal=-*it-1;
9152           return true;
9153         }
9154     }
9155   return false;
9156 }
9157
9158 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,
9159                                      MCAuto<DataArrayInt>& idsInRetColinear, MCAuto<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9160 {
9161   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9162   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9163   int nCells(mesh1D->getNumberOfCells());
9164   if(nCells!=(int)intersectEdge2.size())
9165     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9166   const DataArrayDouble *coo2(mesh1D->getCoords());
9167   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9168   const double *coo2Ptr(coo2->begin());
9169   int offset1(coords1->getNumberOfTuples());
9170   int offset2(offset1+coo2->getNumberOfTuples());
9171   int offset3(offset2+addCoo.size()/2);
9172   std::vector<double> addCooQuad;
9173   MCAuto<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9174   int tmp[4],cicnt(0),kk(0);
9175   for(int i=0;i<nCells;i++)
9176     {
9177       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
9178       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9179       const std::vector<int>& subEdges(intersectEdge2[i]);
9180       int nbSubEdge(subEdges.size()/2);
9181       for(int j=0;j<nbSubEdge;j++,kk++)
9182         {
9183           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));
9184           MCAuto<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9185           INTERP_KERNEL::Edge *e2Ptr(e2);
9186           std::map<int,int>::const_iterator itm;
9187           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9188             {
9189               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9190               itm=mergedNodes.find(subEdges[2*j]);
9191               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9192               itm=mergedNodes.find(subEdges[2*j+1]);
9193               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9194               tmp[3]=offset3+(int)addCooQuad.size()/2;
9195               double tmp2[2];
9196               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9197               cicnt+=4;
9198               cOut->insertAtTheEnd(tmp,tmp+4);
9199               ciOut->pushBackSilent(cicnt);
9200             }
9201           else
9202             {
9203               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9204               itm=mergedNodes.find(subEdges[2*j]);
9205               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9206               itm=mergedNodes.find(subEdges[2*j+1]);
9207               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9208               cicnt+=3;
9209               cOut->insertAtTheEnd(tmp,tmp+3);
9210               ciOut->pushBackSilent(cicnt);
9211             }
9212           int tmp00;
9213           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9214             {
9215               idsInRetColinear->pushBackSilent(kk);
9216               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9217             }
9218         }
9219       e->decrRef();
9220     }
9221   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9222   ret->setConnectivity(cOut,ciOut,true);
9223   MCAuto<DataArrayDouble> arr3(DataArrayDouble::New());
9224   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9225   MCAuto<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9226   std::vector<const DataArrayDouble *> coordss(4);
9227   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9228   MCAuto<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9229   ret->setCoords(arr);
9230   return ret.retn();
9231 }
9232
9233 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9234 {
9235   std::vector<int> allEdges;
9236   for(const int *it2(descBg);it2!=descEnd;it2++)
9237     {
9238       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9239       if(*it2>0)
9240         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9241       else
9242         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9243     }
9244   std::size_t nb(allEdges.size());
9245   if(nb%2!=0)
9246     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9247   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9248   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9249   ret->setCoords(coords);
9250   ret->allocateCells(1);
9251   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9252   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9253     connOut[kk]=allEdges[2*kk];
9254   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9255   return ret.retn();
9256 }
9257
9258 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9259 {
9260   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9261   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9262   std::size_t ii(0);
9263   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9264   if(sz!=std::distance(descBg,descEnd))
9265     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9266   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9267   std::vector<int> allEdges,centers;
9268   const double *coordsPtr(coords->begin());
9269   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9270   int offset(coords->getNumberOfTuples());
9271   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9272     {
9273       INTERP_KERNEL::NormalizedCellType typeOfSon;
9274       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9275       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9276       if(*it2>0)
9277         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9278       else
9279         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9280       if(edge1.size()==2)
9281         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9282       else
9283         {//the current edge has been subsplit -> create corresponding centers.
9284           std::size_t nbOfCentersToAppend(edge1.size()/2);
9285           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9286           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9287           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9288           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9289             {
9290               double tmpp[2];
9291               const double *aa(coordsPtr+2*(*it3++));
9292               const double *bb(coordsPtr+2*(*it3++));
9293               ee->getMiddleOfPoints(aa,bb,tmpp);
9294               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9295               centers.push_back(offset+k);
9296             }
9297         }
9298     }
9299   std::size_t nb(allEdges.size());
9300   if(nb%2!=0)
9301     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9302   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9303   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9304   if(addCoo->empty())
9305     ret->setCoords(coords);
9306   else
9307     {
9308       addCoo->rearrange(2);
9309       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9310       ret->setCoords(addCoo);
9311     }
9312   ret->allocateCells(1);
9313   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9314   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9315     connOut[kk]=allEdges[2*kk];
9316   connOut.insert(connOut.end(),centers.begin(),centers.end());
9317   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9318   return ret.retn();
9319 }
9320
9321 /*!
9322  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9323  * of those edges.
9324  *
9325  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9326  */
9327 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9328 {
9329   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9330   if(!cm.isQuadratic())
9331     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9332   else
9333     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9334 }
9335
9336 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edges)
9337 {
9338   bool isQuad(false);
9339   for(std::vector< MCAuto<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9340     {
9341       const INTERP_KERNEL::Edge *ee(*it);
9342       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9343         isQuad=true;
9344     }
9345   if(!isQuad)
9346     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9347   else
9348     {
9349       const double *coo(mesh2D->getCoords()->begin());
9350       std::size_t sz(conn.size());
9351       std::vector<double> addCoo;
9352       std::vector<int> conn2(conn);
9353       int offset(mesh2D->getNumberOfNodes());
9354       for(std::size_t i=0;i<sz;i++)
9355         {
9356           double tmp[2];
9357           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9358           addCoo.insert(addCoo.end(),tmp,tmp+2);
9359           conn2.push_back(offset+(int)i);
9360         }
9361       mesh2D->getCoords()->rearrange(1);
9362       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9363       mesh2D->getCoords()->rearrange(2);
9364       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9365     }
9366 }
9367
9368 /*!
9369  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9370  *
9371  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9372  * a set of edges defined in \a splitMesh1D.
9373  */
9374 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edge1BisPtr,
9375                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& out1)
9376 {
9377   std::size_t nb(edge1Bis.size()/2);
9378   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9379   int iEnd(splitMesh1D->getNumberOfCells());
9380   if(iEnd==0)
9381     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9382   std::size_t ii,jj;
9383   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9384   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9385   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9386   //
9387   if(jj==nb)
9388     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9389       out0.resize(1); out1.resize(1);
9390       std::vector<int>& connOut(out0[0]);
9391       connOut.resize(nbOfEdgesOf2DCellSplit);
9392       std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9393       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9394       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9395         {
9396           connOut[kk]=edge1Bis[2*kk];
9397           edgesPtr[kk]=edge1BisPtr[2*kk];
9398         }
9399     }
9400   else
9401     {
9402       // [i,iEnd[ contains the
9403       out0.resize(2); out1.resize(2);
9404       std::vector<int>& connOutLeft(out0[0]);
9405       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9406       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9407       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eright(out1[1]);
9408       for(std::size_t k=ii;k<jj+1;k++)
9409         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9410       std::vector< MCAuto<INTERP_KERNEL::Edge> > ees(iEnd);
9411       for(int ik=0;ik<iEnd;ik++)
9412         {
9413           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9414           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9415           ees[ik]=ee;
9416         }
9417       for(int ik=iEnd-1;ik>=0;ik--)
9418         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9419       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9420         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9421       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9422       for(int ik=0;ik<iEnd;ik++)
9423         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9424       eright.insert(eright.end(),ees.begin(),ees.end());
9425     }
9426 }
9427
9428 /// @endcond
9429
9430 /// @cond INTERNAL
9431
9432 struct CellInfo
9433 {
9434 public:
9435   CellInfo() { }
9436   CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9437 public:
9438   std::vector<int> _edges;
9439   std::vector< MCAuto<INTERP_KERNEL::Edge> > _edges_ptr;
9440 };
9441
9442 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr)
9443 {
9444   std::size_t nbe(edges.size());
9445   std::vector<int> edges2(2*nbe); std::vector< MCAuto<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9446   for(std::size_t i=0;i<nbe;i++)
9447     {
9448       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9449       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9450     }
9451   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9452   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9453   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9454 }
9455
9456 class EdgeInfo
9457 {
9458 public:
9459   EdgeInfo(int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9460   EdgeInfo(int istart, int iend, int pos, const MCAuto<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9461   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9462   void somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9463   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9464 private:
9465   int _istart;
9466   int _iend;
9467   MCAuto<MEDCouplingUMesh> _mesh;
9468   MCAuto<INTERP_KERNEL::Edge> _edge;
9469   int _left;
9470   int _right;
9471 };
9472
9473 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9474 {
9475   const MEDCouplingUMesh *mesh(_mesh);
9476   if(mesh)
9477     return ;
9478   if(_right<pos)
9479     return ;
9480   if(_left>pos)
9481     { _left++; _right++; return ; }
9482   if(_right==pos)
9483     {
9484       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9485       if((isLeft && isRight) || (!isLeft && !isRight))
9486         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9487       if(isLeft)
9488         return ;
9489       if(isRight)
9490         {
9491           _right++;
9492           return ;
9493         }
9494     }
9495   if(_left==pos)
9496     {
9497       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9498       if((isLeft && isRight) || (!isLeft && !isRight))
9499         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9500       if(isLeft)
9501         {
9502           _right++;
9503           return ;
9504         }
9505       if(isRight)
9506         {
9507           _left++;
9508           _right++;
9509           return ;
9510         }
9511     }
9512 }
9513
9514 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9515 {
9516   const MEDCouplingUMesh *mesh(_mesh);
9517   if(!mesh)
9518     {
9519       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9520     }
9521   else
9522     {// not fully splitting cell case
9523       if(mesh2D->getNumberOfCells()==1)
9524         {//little optimization. 1 cell no need to find in which cell mesh is !
9525           neighbors[0]=offset; neighbors[1]=offset;
9526           return;
9527         }
9528       else
9529         {
9530           MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9531           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9532           if(cellId==-1)
9533             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9534           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9535         }
9536     }
9537 }
9538
9539 class VectorOfCellInfo
9540 {
9541 public:
9542   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9543   std::size_t size() const { return _pool.size(); }
9544   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9545   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);
9546   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9547   const std::vector< MCAuto<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9548   MCAuto<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9549   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9550 private:
9551   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9552   void updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9553   const CellInfo& get(int pos) const;
9554   CellInfo& get(int pos);
9555 private:
9556   std::vector<CellInfo> _pool;
9557   MCAuto<MEDCouplingUMesh> _ze_mesh;
9558   std::vector<EdgeInfo> _edge_info;
9559 };
9560
9561 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9562 {
9563   _pool[0]._edges=edges;
9564   _pool[0]._edges_ptr=edgesPtr;
9565 }
9566
9567 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9568 {
9569   if(_pool.empty())
9570     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9571   if(_pool.size()==1)
9572     return 0;
9573   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9574   if(!zeMesh)
9575     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9576   MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9577   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9578 }
9579
9580 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)
9581 {
9582   get(pos);//to check pos
9583   bool isFast(pos==0 && _pool.size()==1);
9584   std::size_t sz(edges.size());
9585   // dealing with edges
9586   if(sz==1)
9587     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9588   else
9589     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9590   //
9591   std::vector<CellInfo> pool(_pool.size()-1+sz);
9592   for(int i=0;i<pos;i++)
9593     pool[i]=_pool[i];
9594   for(std::size_t j=0;j<sz;j++)
9595     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9596   for(int i=pos+1;i<(int)_pool.size();i++)
9597     pool[i+sz-1]=_pool[i];
9598   _pool=pool;
9599   //
9600   if(sz==2)
9601     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9602   //
9603   if(isFast)
9604     {
9605       _ze_mesh=mesh;
9606       return ;
9607     }
9608   //
9609   std::vector< MCAuto<MEDCouplingUMesh> > ms;
9610   if(pos>0)
9611     {
9612       MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(0,pos,true)));
9613       ms.push_back(elt);
9614     }
9615   ms.push_back(mesh);
9616   if(pos<_ze_mesh->getNumberOfCells()-1)
9617   {
9618     MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(pos+1,_ze_mesh->getNumberOfCells(),true)));
9619     ms.push_back(elt);
9620   }
9621   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9622   for(std::size_t j=0;j<ms2.size();j++)
9623     ms2[j]=ms[j];
9624   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9625 }
9626
9627 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9628 {
9629   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9630 }
9631
9632 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9633 {
9634   if(pos<0)
9635     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9636   int ret(0);
9637   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9638     {
9639       if((*it).isInMyRange(pos))
9640         return ret;
9641     }
9642   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9643 }
9644
9645 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9646 {
9647   get(pos);//to check;
9648   if(_edge_info.empty())
9649     return ;
9650   std::size_t sz(_edge_info.size()-1);
9651   for(std::size_t i=0;i<sz;i++)
9652     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9653 }
9654
9655 const CellInfo& VectorOfCellInfo::get(int pos) const
9656 {
9657   if(pos<0 || pos>=(int)_pool.size())
9658     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9659   return _pool[pos];
9660 }
9661
9662 CellInfo& VectorOfCellInfo::get(int pos)
9663 {
9664   if(pos<0 || pos>=(int)_pool.size())
9665     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9666   return _pool[pos];
9667 }
9668
9669 /*!
9670  * Given :
9671  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9672  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9673  *
9674  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9675  *
9676  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9677  *
9678  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9679  */
9680 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9681                                          MCAuto<DataArrayInt>& idsLeftRight)
9682 {
9683   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9684   if(nbCellsInSplitMesh1D==0)
9685     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9686   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9687   std::size_t nb(allEdges.size()),jj;
9688   if(nb%2!=0)
9689     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9690   std::vector<int> edge1Bis(nb*2);
9691   std::vector< MCAuto<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9692   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9693   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9694   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9695   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9696   //
9697   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9698   int *idsLeftRightPtr(idsLeftRight->getPointer());
9699   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9700   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9701     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9702       int iEnd(iStart);
9703       for(;iEnd<nbCellsInSplitMesh1D;)
9704         {
9705           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9706           if(jj!=nb)
9707             break;
9708           else
9709             iEnd++;
9710         }
9711       if(iEnd<nbCellsInSplitMesh1D)
9712         iEnd++;
9713       //
9714       MCAuto<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelfSlice(iStart,iEnd,1,true)));
9715       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9716       //
9717       MCAuto<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9718       retTmp->setCoords(splitMesh1D->getCoords());
9719       retTmp->allocateCells();
9720
9721       std::vector< std::vector<int> > out0;
9722       std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > > out1;
9723
9724       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9725       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9726         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9727       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9728       //
9729       iStart=iEnd;
9730     }
9731   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9732     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9733   return pool.getZeMesh().retn();
9734 }
9735
9736 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9737                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9738                                      MCAuto<DataArrayInt>& idsLeftRight)
9739 {
9740   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9741   //
9742   std::vector<int> allEdges;
9743   std::vector< MCAuto<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9744   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9745     {
9746       int edgeId(std::abs(*it)-1);
9747       std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9748       MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9749       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9750       if(*it>0)
9751         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9752       else
9753         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9754       std::size_t sz(edge1.size());
9755       for(std::size_t cnt=0;cnt<sz;cnt++)
9756         allEdgesPtr.push_back(ee);
9757     }
9758   //
9759   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9760 }
9761
9762 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9763 {
9764   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9765     {//easy case comparison not
9766       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9767     }
9768   else if(typ1.isQuadratic() && typ2.isQuadratic())
9769     {
9770       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9771       if(!status0)
9772         return false;
9773       if(conn1[2]==conn2[2])
9774         return true;
9775       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9776       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9777       return dist<eps;
9778     }
9779   else
9780     {//only one is quadratic
9781       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9782       if(!status0)
9783         return false;
9784       const double *a(0),*bb(0),*be(0);
9785       if(typ1.isQuadratic())
9786         {
9787           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9788         }
9789       else
9790         {
9791           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9792         }
9793       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9794       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9795       return dist<eps;
9796     }
9797 }
9798
9799 /*!
9800  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9801  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9802  *
9803  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9804  */
9805 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9806 {
9807   if(candidatesIn2DEnd==candidatesIn2DBg)
9808     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9809   const double *coo(mesh2DSplit->getCoords()->begin());
9810   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9811     return *candidatesIn2DBg;
9812   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9813   MCAuto<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9814   if(cellIdInMesh1DSplitRelative<0)
9815     cur1D->changeOrientationOfCells();
9816   const int *c1D(cur1D->getNodalConnectivity()->begin());
9817   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9818   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9819     {
9820       MCAuto<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9821       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9822       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9823       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9824       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9825       for(unsigned it2=0;it2<sz;it2++)
9826         {
9827           INTERP_KERNEL::NormalizedCellType typeOfSon;
9828           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9829           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9830           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9831             return *it;
9832         }
9833     }
9834   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9835 }
9836
9837 /// @endcond
9838
9839 /*!
9840  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9841  * 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
9842  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9843  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9844  *
9845  * \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
9846  *                      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)
9847  * \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
9848  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9849  * \param [in] eps - precision used to perform intersections and localization operations.
9850  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9851  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9852  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9853  *                               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.
9854  * \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
9855  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9856  *                               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.
9857  *
9858  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9859  */
9860 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9861 {
9862   if(!mesh2D || !mesh1D)
9863     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9864   mesh2D->checkFullyDefined();
9865   mesh1D->checkFullyDefined();
9866   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9867   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9868     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9869   // Step 1: compute all edge intersections (new nodes)
9870   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9871   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9872   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9873   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9874   //
9875   // Build desc connectivity
9876   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9877   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9878   MCAuto<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9879   std::map<int,int> mergedNodes;
9880   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9881   // use mergeNodes to fix intersectEdge1
9882   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9883     {
9884       std::size_t n((*it0).size()/2);
9885       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9886       std::map<int,int>::const_iterator it1;
9887       it1=mergedNodes.find(eltStart);
9888       if(it1!=mergedNodes.end())
9889         (*it0)[0]=(*it1).second;
9890       it1=mergedNodes.find(eltEnd);
9891       if(it1!=mergedNodes.end())
9892         (*it0)[2*n-1]=(*it1).second;
9893     }
9894   //
9895   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
9896   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9897   // Step 2: re-order newly created nodes according to the ordering found in m2
9898   std::vector< std::vector<int> > intersectEdge2;
9899   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9900   subDiv2.clear();
9901   // Step 3: compute splitMesh1D
9902   MCAuto<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9903   MCAuto<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9904   MCAuto<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9905       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9906   MCAuto<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9907   MCAuto<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9908   // deal with cells in mesh2D that are not cut but only some of their edges are
9909   MCAuto<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCopy());
9910   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9911   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9912   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
9913   if(!idsInDesc2DToBeRefined->empty())
9914     {
9915       DataArrayInt *out0(0),*outi0(0);
9916       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9917       MCAuto<DataArrayInt> outi0s(outi0);
9918       out0s=out0;
9919       out0s=out0s->buildUnique();
9920       out0s->sort(true);
9921     }
9922   //
9923   MCAuto<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9924   MCAuto<DataArrayDouble> baryRet1(ret1NonCol->computeCellCenterOfMass());
9925   MCAuto<DataArrayInt> elts,eltsIndex;
9926   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9927   MCAuto<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9928   MCAuto<DataArrayInt> eltsIndex3(eltsIndex2->findIdsEqual(1));
9929   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9930     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9931   MCAuto<DataArrayInt> cellsToBeModified(elts->buildUnique());
9932   MCAuto<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9933   if((DataArrayInt *)out0s)
9934     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9935   std::vector< MCAuto<MEDCouplingUMesh> > outMesh2DSplit;
9936   // OK all is ready to insert in ret2 mesh
9937   if(!untouchedCells->empty())
9938     {// the most easy part, cells in mesh2D not impacted at all
9939       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9940       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9941       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9942     }
9943   if((DataArrayInt *)out0s)
9944     {// here dealing with cells in out0s but not in cellsToBeModified
9945       MCAuto<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9946       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9947       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9948         {
9949           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9950           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9951         }
9952       int offset(ret2->getNumberOfTuples());
9953       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9954       MCAuto<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9955       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9956       int kk(0),*ret3ptr(partOfRet3->getPointer());
9957       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9958         {
9959           int faceId(std::abs(*it)-1);
9960           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9961             {
9962               int tmp(fewModifiedCells->findIdFirstEqual(*it2));
9963               if(tmp!=-1)
9964                 {
9965                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9966                     ret3ptr[2*kk]=tmp+offset;
9967                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9968                     ret3ptr[2*kk+1]=tmp+offset;
9969                 }
9970               else
9971                 {//the current edge is shared by a 2D cell that will be split just after
9972                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9973                     ret3ptr[2*kk]=-(*it2+1);
9974                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9975                     ret3ptr[2*kk+1]=-(*it2+1);
9976                 }
9977             }
9978         }
9979       m1Desc->setCoords(ret1->getCoords());
9980       ret1NonCol->setCoords(ret1->getCoords());
9981       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9982       if(!outMesh2DSplit.empty())
9983         {
9984           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9985           for(std::vector< MCAuto<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9986             (*itt)->setCoords(da);
9987         }
9988     }
9989   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9990   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9991     {
9992       MCAuto<DataArrayInt> idsNonColPerCell(elts->findIdsEqual(*it));
9993       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9994       MCAuto<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9995       MCAuto<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9996       MCAuto<DataArrayInt> partOfRet3;
9997       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));
9998       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9999       outMesh2DSplit.push_back(splitOfOneCell);
10000       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
10001         ret2->pushBackSilent(*it);
10002     }
10003   //
10004   std::size_t nbOfMeshes(outMesh2DSplit.size());
10005   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
10006   for(std::size_t i=0;i<nbOfMeshes;i++)
10007     tmp[i]=outMesh2DSplit[i];
10008   //
10009   ret1->getCoords()->setInfoOnComponents(compNames);
10010   MCAuto<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
10011   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
10012   ret3->rearrange(1);
10013   MCAuto<DataArrayInt> edgesToDealWith(ret3->findIdsStricltyNegative());
10014   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
10015     {
10016       int old2DCellId(-ret3->getIJ(*it,0)-1);
10017       MCAuto<DataArrayInt> candidates(ret2->findIdsEqual(old2DCellId));
10018       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
10019     }
10020   ret3->changeValue(std::numeric_limits<int>::max(),-1);
10021   ret3->rearrange(2);
10022   //
10023   splitMesh1D=ret1.retn();
10024   splitMesh2D=ret2D.retn();
10025   cellIdInMesh2D=ret2.retn();
10026   cellIdInMesh1D=ret3.retn();
10027 }
10028
10029 /**
10030  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
10031  * (newly created) nodes corresponding to the edge intersections.
10032  * Output params:
10033  * @param[out] cr, crI connectivity of the resulting mesh
10034  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
10035  * TODO: describe input parameters
10036  */
10037 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
10038                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
10039                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
10040                                                          const std::vector<double>& addCoords,
10041                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
10042 {
10043   static const int SPACEDIM=2;
10044   const double *coo1(m1->getCoords()->getConstPointer());
10045   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
10046   int offset1(m1->getNumberOfNodes());
10047   const double *coo2(m2->getCoords()->getConstPointer());
10048   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
10049   int offset2(offset1+m2->getNumberOfNodes());
10050   int offset3(offset2+((int)addCoords.size())/2);
10051   MCAuto<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
10052   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10053   // Here a BBTree on 2D-cells, not on segments:
10054   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
10055   int ncell1(m1->getNumberOfCells());
10056   crI.push_back(0);
10057   for(int i=0;i<ncell1;i++)
10058     {
10059       std::vector<int> candidates2;
10060       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10061       std::map<INTERP_KERNEL::Node *,int> mapp;
10062       std::map<int,INTERP_KERNEL::Node *> mappRev;
10063       INTERP_KERNEL::QuadraticPolygon pol1;
10064       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
10065       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
10066       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
10067       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
10068       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
10069       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
10070           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
10071       //
10072       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
10073       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
10074       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
10075       for(it1.first();!it1.finished();it1.next())
10076         edges1.insert(it1.current()->getPtr());
10077       //
10078       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
10079       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10080       int ii=0;
10081       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10082         {
10083           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10084           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10085           // Complete mapping with elements coming from the current cell it2 in mesh2:
10086           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10087           // pol2 is the new QP in the final merged result.
10088           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10089               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10090         }
10091       ii=0;
10092       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10093         {
10094           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10095           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10096           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10097           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10098         }
10099       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10100       // by m2 but that we still want to keep in the final result.
10101       if(!edges1.empty())
10102         {
10103           try
10104           {
10105               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10106           }
10107           catch(INTERP_KERNEL::Exception& e)
10108           {
10109               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();
10110               throw INTERP_KERNEL::Exception(oss.str().c_str());
10111           }
10112         }
10113       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10114         (*it).second->decrRef();
10115     }
10116 }
10117
10118 /**
10119  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10120  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10121  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10122  * The caller is to deal with the resulting DataArrayInt.
10123  *  \throw If the coordinate array is not set.
10124  *  \throw If the nodal connectivity of the cells is not defined.
10125  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10126  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10127  *
10128  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10129  */
10130 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10131 {
10132   checkFullyDefined();
10133   if(getMeshDimension()!=1)
10134     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10135
10136   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10137   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10138   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10139   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10140   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10141   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10142   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10143   const int * dsi(_dsi->getConstPointer());
10144   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
10145   m_points=0;
10146   if (dsii->getNumberOfTuples())
10147     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10148
10149   int nc(getNumberOfCells());
10150   MCAuto<DataArrayInt> result(DataArrayInt::New());
10151   result->alloc(nc,1);
10152
10153   // set of edges not used so far
10154   std::set<int> edgeSet;
10155   for (int i=0; i<nc; edgeSet.insert(i), i++);
10156
10157   int startSeg=0;
10158   int newIdx=0;
10159   // while we have points with only one neighbor segments
10160   do
10161     {
10162       std::list<int> linePiece;
10163       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10164       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10165         {
10166           // Fill the list forward (resp. backward) from the start segment:
10167           int activeSeg = startSeg;
10168           int prevPointId = -20;
10169           int ptId;
10170           while (!edgeSet.empty())
10171             {
10172               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10173                 {
10174                   if (direction==0)
10175                     linePiece.push_back(activeSeg);
10176                   else
10177                     linePiece.push_front(activeSeg);
10178                   edgeSet.erase(activeSeg);
10179                 }
10180
10181               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10182               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10183               if (dsi[ptId] == 1) // hitting the end of the line
10184                 break;
10185               prevPointId = ptId;
10186               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10187               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10188             }
10189         }
10190       // Done, save final piece into DA:
10191       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10192       newIdx += linePiece.size();
10193
10194       // identify next valid start segment (one which is not consumed)
10195       if(!edgeSet.empty())
10196         startSeg = *(edgeSet.begin());
10197     }
10198   while (!edgeSet.empty());
10199   return result.retn();
10200 }
10201
10202 /// @cond INTERNAL
10203
10204 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10205 {
10206   MCAuto<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10207   std::map<MCAuto<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10208   if(it==m.end())
10209     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10210   int v((*it).second);
10211   if(v==forbVal0 || v==forbVal1)
10212     return ;
10213   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10214     isect.push_back(v);
10215 }
10216
10217 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10218 {
10219   int sz(c.size());
10220   if(sz<=1)
10221     return false;
10222   bool presenceOfOn(false);
10223   for(int i=0;i<sz;i++)
10224     {
10225       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10226       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10227         continue ;
10228       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10229       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10230     }
10231   return presenceOfOn;
10232 }
10233
10234 /// @endcond
10235
10236 /**
10237  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10238  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10239  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10240  * a minimal creation of new nodes is wanted.
10241  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10242  * nodes if a SEG3 is split without information of middle.
10243  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10244  * avoid to have a non conform mesh.
10245  *
10246  * \return int - the number of new nodes created (in most of cases 0).
10247  * 
10248  * \throw If \a this is not coherent.
10249  * \throw If \a this has not spaceDim equal to 2.
10250  * \throw If \a this has not meshDim equal to 2.
10251  * \throw If some subcells needed to be split are orphan.
10252  * \sa MEDCouplingUMesh::conformize2D
10253  */
10254 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10255 {
10256   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10257     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10258   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10259   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10260     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10261   if(midOpt==0 && midOptI==0)
10262     {
10263       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10264       return 0;
10265     }
10266   else if(midOpt!=0 && midOptI!=0)
10267     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10268   else
10269     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10270 }
10271
10272 /*!
10273  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10274  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10275  * 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
10276  * 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).
10277  * 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.
10278  * 
10279  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10280  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10281  *
10282  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10283  * This method expects that all nodes in \a this are not closer than \a eps.
10284  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10285  * 
10286  * \param [in] eps the relative error to detect merged edges.
10287  * \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
10288  *                           that the user is expected to deal with.
10289  *
10290  * \throw If \a this is not coherent.
10291  * \throw If \a this has not spaceDim equal to 2.
10292  * \throw If \a this has not meshDim equal to 2.
10293  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10294  */
10295 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10296 {
10297   static const int SPACEDIM=2;
10298   checkConsistencyLight();
10299   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10300     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10301   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10302   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10303   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10304   MCAuto<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10305   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10306   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10307   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10308   std::vector<double> addCoo;
10309   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10310   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10311   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10312   for(int i=0;i<nDescCell;i++)
10313     {
10314       std::vector<int> candidates;
10315       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10316       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10317         if(*it>i)
10318           {
10319             std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10320             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10321                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10322             INTERP_KERNEL::MergePoints merge;
10323             INTERP_KERNEL::QuadraticPolygon c1,c2;
10324             e1->intersectWith(e2,merge,c1,c2);
10325             e1->decrRef(); e2->decrRef();
10326             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10327               overlapEdge[i].push_back(*it);
10328             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10329               overlapEdge[*it].push_back(i);
10330           }
10331     }
10332   // splitting done. sort intersect point in intersectEdge.
10333   std::vector< std::vector<int> > middle(nDescCell);
10334   int nbOf2DCellsToBeSplit(0);
10335   bool middleNeedsToBeUsed(false);
10336   std::vector<bool> cells2DToTreat(nDescCell,false);
10337   for(int i=0;i<nDescCell;i++)
10338     {
10339       std::vector<int>& isect(intersectEdge[i]);
10340       int sz((int)isect.size());
10341       if(sz>1)
10342         {
10343           std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10344           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10345           e->sortSubNodesAbs(coords,isect);
10346           e->decrRef();
10347         }
10348       if(sz!=0)
10349         {
10350           int idx0(rdi[i]),idx1(rdi[i+1]);
10351           if(idx1-idx0!=1)
10352             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10353           if(!cells2DToTreat[rd[idx0]])
10354             {
10355               cells2DToTreat[rd[idx0]]=true;
10356               nbOf2DCellsToBeSplit++;
10357             }
10358           // try to reuse at most eventual 'middle' of SEG3
10359           std::vector<int>& mid(middle[i]);
10360           mid.resize(sz+1,-1);
10361           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10362             {
10363               middleNeedsToBeUsed=true;
10364               const std::vector<int>& candidates(overlapEdge[i]);
10365               std::vector<int> trueCandidates;
10366               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10367                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10368                   trueCandidates.push_back(*itc);
10369               int stNode(c[ci[i]+1]),endNode(isect[0]);
10370               for(int j=0;j<sz+1;j++)
10371                 {
10372                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10373                     {
10374                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10375                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10376                         { mid[j]=*itc; break; }
10377                     }
10378                   stNode=endNode;
10379                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10380                 }
10381             }
10382         }
10383     }
10384   MCAuto<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10385   if(nbOf2DCellsToBeSplit==0)
10386     return ret.retn();
10387   //
10388   int *retPtr(ret->getPointer());
10389   for(int i=0;i<nCell;i++)
10390     if(cells2DToTreat[i])
10391       *retPtr++=i;
10392   //
10393   MCAuto<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10394   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10395   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10396   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10397   if(middleNeedsToBeUsed)
10398     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10399   MCAuto<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10400   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10401   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.
10402   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10403   {
10404     bool areNodesMerged; int newNbOfNodes;
10405     if(nbOfNodesCreated!=0)
10406       MCAuto<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10407   }
10408   return ret.retn();
10409 }
10410
10411 /*!
10412  * 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.
10413  * 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).
10414  * 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
10415  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10416  * 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
10417  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10418  *
10419  * 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
10420  * using new instance, idem for coordinates.
10421  *
10422  * 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.
10423  * 
10424  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10425  *
10426  * \throw If \a this is not coherent.
10427  * \throw If \a this has not spaceDim equal to 2.
10428  * \throw If \a this has not meshDim equal to 2.
10429  * 
10430  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10431  */
10432 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10433 {
10434   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10435   checkConsistencyLight();
10436   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10437     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10438   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10439   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10440   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10441   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10442   MCAuto<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10443   MCAuto<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10444   const double *coords(_coords->begin());
10445   int *newciptr(newci->getPointer());
10446   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10447     {
10448       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10449         ret->pushBackSilent(i);
10450       newciptr[1]=newc->getNumberOfTuples();
10451     }
10452   //
10453   if(ret->empty())
10454     return ret.retn();
10455   if(!appendedCoords->empty())
10456     {
10457       appendedCoords->rearrange(2);
10458       MCAuto<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10459       //non const part
10460       setCoords(newCoords);
10461     }
10462   //non const part
10463   setConnectivity(newc,newci,true);
10464   return ret.retn();
10465 }
10466
10467 /*!
10468  * \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.
10469  *                               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.
10470  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10471  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10472  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10473  * \param [out] addCoo - nodes to be append at the end
10474  * \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.
10475  */
10476 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10477                                          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)
10478 {
10479   static const int SPACEDIM=2;
10480   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10481   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10482   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10483   // Build BB tree of all edges in the tool mesh (second mesh)
10484   MCAuto<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10485   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10486   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10487   intersectEdge1.resize(nDescCell1);
10488   colinear2.resize(nDescCell2);
10489   subDiv2.resize(nDescCell2);
10490   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10491
10492   std::vector<int> candidates1(1);
10493   int offset1(m1Desc->getNumberOfNodes());
10494   int offset2(offset1+m2Desc->getNumberOfNodes());
10495   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10496     {
10497       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10498       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10499       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10500         {
10501           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10502           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10503           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10504           candidates1[0]=i;
10505           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10506           // 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
10507           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10508           std::set<INTERP_KERNEL::Node *> nodes;
10509           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10510           std::size_t szz(nodes.size());
10511           std::vector< MCAuto<INTERP_KERNEL::Node> > nodesSafe(szz);
10512           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10513           for(std::size_t iii=0;iii<szz;iii++,itt++)
10514             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10515           // end of protection
10516           // Performs egde cutting:
10517           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10518           delete pol2;
10519           delete pol1;
10520         }
10521       else
10522         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10523         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10524     }
10525 }
10526
10527 /*!
10528  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10529  * It builds the descending connectivity of the two meshes, and then using a binary tree
10530  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10531  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10532  */
10533 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10534                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10535                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10536                                                    std::vector<double>& addCoo,
10537                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10538 {
10539   // Build desc connectivity
10540   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10541   desc2=DataArrayInt::New();
10542   descIndx2=DataArrayInt::New();
10543   revDesc2=DataArrayInt::New();
10544   revDescIndx2=DataArrayInt::New();
10545   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10546   MCAuto<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10547   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10548   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10549   MCAuto<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10550   std::map<int,int> notUsedMap;
10551   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10552   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10553   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10554 }
10555
10556 /*!
10557  * This method performs the 2nd step of Partition of 2D mesh.
10558  * This method has 4 inputs :
10559  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10560  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10561  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10562  * 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'
10563  * Nodes end up lying consecutively on a cutted edge.
10564  * \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.
10565  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10566  * \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.
10567  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10568  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10569  */
10570 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10571                                            const std::vector<double>& addCoo,
10572                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10573 {
10574   int offset1=m1->getNumberOfNodes();
10575   int ncell=m2->getNumberOfCells();
10576   const int *c=m2->getNodalConnectivity()->getConstPointer();
10577   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10578   const double *coo=m2->getCoords()->getConstPointer();
10579   const double *cooBis=m1->getCoords()->getConstPointer();
10580   int offset2=offset1+m2->getNumberOfNodes();
10581   intersectEdge.resize(ncell);
10582   for(int i=0;i<ncell;i++,cI++)
10583     {
10584       const std::vector<int>& divs=subDiv[i];
10585       int nnode=cI[1]-cI[0]-1;
10586       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10587       std::map<INTERP_KERNEL::Node *, int> mapp22;
10588       for(int j=0;j<nnode;j++)
10589         {
10590           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10591           int nnid=c[(*cI)+j+1];
10592           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10593           mapp22[nn]=nnid+offset1;
10594         }
10595       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10596       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10597         ((*it).second.first)->decrRef();
10598       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10599       std::map<INTERP_KERNEL::Node *,int> mapp3;
10600       for(std::size_t j=0;j<divs.size();j++)
10601         {
10602           int id=divs[j];
10603           INTERP_KERNEL::Node *tmp=0;
10604           if(id<offset1)
10605             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10606           else if(id<offset2)
10607             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10608           else
10609             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10610           addNodes[j]=tmp;
10611           mapp3[tmp]=id;
10612         }
10613       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10614       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10615         (*it)->decrRef();
10616       e->decrRef();
10617     }
10618 }
10619
10620 /*!
10621  * 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).
10622  * 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
10623  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10624  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10625  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10626  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10627  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10628  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10629  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10630  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10631  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10632  * \param [out] cut3DSuf input/output param.
10633  */
10634 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10635                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10636                                                    const int *desc, const int *descIndx, 
10637                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10638 {
10639   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10640   int nbOf3DSurfCell=(int)cut3DSurf.size();
10641   for(int i=0;i<nbOf3DSurfCell;i++)
10642     {
10643       std::vector<int> res;
10644       int offset=descIndx[i];
10645       int nbOfSeg=descIndx[i+1]-offset;
10646       for(int j=0;j<nbOfSeg;j++)
10647         {
10648           int edgeId=desc[offset+j];
10649           int status=cut3DCurve[edgeId];
10650           if(status!=-2)
10651             {
10652               if(status>-1)
10653                 res.push_back(status);
10654               else
10655                 {
10656                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10657                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10658                 }
10659             }
10660         }
10661       switch(res.size())
10662       {
10663         case 2:
10664           {
10665             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10666             break;
10667           }
10668         case 1:
10669         case 0:
10670           {
10671             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10672             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10673             if(res.size()==2)
10674               {
10675                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10676               }
10677             else
10678               {
10679                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10680               }
10681             break;
10682           }
10683         default:
10684           {// case when plane is on a multi colinear edge of a polyhedron
10685             if((int)res.size()==2*nbOfSeg)
10686               {
10687                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10688               }
10689             else
10690               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10691           }
10692       }
10693     }
10694 }
10695
10696 /*!
10697  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10698  * 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).
10699  * 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
10700  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10701  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10702  * \param desc is the descending connectivity 3D->3DSurf
10703  * \param descIndx is the descending connectivity index 3D->3DSurf
10704  */
10705 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10706                                                   const int *desc, const int *descIndx,
10707                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10708 {
10709   checkFullyDefined();
10710   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10711     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10712   const int *nodal3D=_nodal_connec->getConstPointer();
10713   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10714   int nbOfCells=getNumberOfCells();
10715   for(int i=0;i<nbOfCells;i++)
10716     {
10717       std::map<int, std::set<int> > m;
10718       int offset=descIndx[i];
10719       int nbOfFaces=descIndx[i+1]-offset;
10720       int start=-1;
10721       int end=-1;
10722       for(int j=0;j<nbOfFaces;j++)
10723         {
10724           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10725           if(p.first!=-1 && p.second!=-1)
10726             {
10727               if(p.first!=-2)
10728                 {
10729                   start=p.first; end=p.second;
10730                   m[p.first].insert(p.second);
10731                   m[p.second].insert(p.first);
10732                 }
10733               else
10734                 {
10735                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10736                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10737                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10738                   INTERP_KERNEL::NormalizedCellType cmsId;
10739                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10740                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10741                   for(unsigned k=0;k<nbOfNodesSon;k++)
10742                     {
10743                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10744                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10745                     }
10746                 }
10747             }
10748         }
10749       if(m.empty())
10750         continue;
10751       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10752       int prev=end;
10753       while(end!=start)
10754         {
10755           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10756           const std::set<int>& s=(*it).second;
10757           std::set<int> s2; s2.insert(prev);
10758           std::set<int> s3;
10759           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10760           if(s3.size()==1)
10761             {
10762               int val=*s3.begin();
10763               conn.push_back(start);
10764               prev=start;
10765               start=val;
10766             }
10767           else
10768             start=end;
10769         }
10770       conn.push_back(end);
10771       if(conn.size()>3)
10772         {
10773           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10774           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10775           cellIds->pushBackSilent(i);
10776         }
10777     }
10778 }
10779
10780 /*!
10781  * 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
10782  * 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
10783  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10784  * 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
10785  * 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.
10786  * 
10787  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10788  */
10789 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10790 {
10791   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10792   if(sz>=4)
10793     {
10794       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10795       if(cm.getDimension()==2)
10796         {
10797           const int *node=nodalConnBg+1;
10798           int startNode=*node++;
10799           double refX=coords[2*startNode];
10800           for(;node!=nodalConnEnd;node++)
10801             {
10802               if(coords[2*(*node)]<refX)
10803                 {
10804                   startNode=*node;
10805                   refX=coords[2*startNode];
10806                 }
10807             }
10808           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10809           refX=1e300;
10810           double tmp1;
10811           double tmp2[2];
10812           double angle0=-M_PI/2;
10813           //
10814           int nextNode=-1;
10815           int prevNode=-1;
10816           double resRef;
10817           double angleNext=0.;
10818           while(nextNode!=startNode)
10819             {
10820               nextNode=-1;
10821               resRef=1e300;
10822               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10823                 {
10824                   if(*node!=tmpOut.back() && *node!=prevNode)
10825                     {
10826                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10827                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10828                       double res;
10829                       if(angleM<=angle0)
10830                         res=angle0-angleM;
10831                       else
10832                         res=angle0-angleM+2.*M_PI;
10833                       if(res<resRef)
10834                         {
10835                           nextNode=*node;
10836                           resRef=res;
10837                           angleNext=angleM;
10838                         }
10839                     }
10840                 }
10841               if(nextNode!=startNode)
10842                 {
10843                   angle0=angleNext-M_PI;
10844                   if(angle0<-M_PI)
10845                     angle0+=2*M_PI;
10846                   prevNode=tmpOut.back();
10847                   tmpOut.push_back(nextNode);
10848                 }
10849             }
10850           std::vector<int> tmp3(2*(sz-1));
10851           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10852           std::copy(nodalConnBg+1,nodalConnEnd,it);
10853           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10854             {
10855               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10856               return false;
10857             }
10858           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10859             {
10860               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10861               return false;
10862             }
10863           else
10864             {
10865               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10866               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10867               return true;
10868             }
10869         }
10870       else
10871         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10872     }
10873   else
10874     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10875 }
10876
10877 /*!
10878  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10879  * 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.
10880  * 
10881  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10882  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10883  * \param [in,out] arr array in which the remove operation will be done.
10884  * \param [in,out] arrIndx array in the remove operation will modify
10885  * \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])
10886  * \return true if \b arr and \b arrIndx have been modified, false if not.
10887  */
10888 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10889 {
10890   if(!arrIndx || !arr)
10891     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10892   if(offsetForRemoval<0)
10893     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10894   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10895   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10896   int *arrIPtr=arrIndx->getPointer();
10897   *arrIPtr++=0;
10898   int previousArrI=0;
10899   const int *arrPtr=arr->getConstPointer();
10900   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10901   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10902     {
10903       if(*arrIPtr-previousArrI>offsetForRemoval)
10904         {
10905           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10906             {
10907               if(s.find(*work)==s.end())
10908                 arrOut.push_back(*work);
10909             }
10910         }
10911       previousArrI=*arrIPtr;
10912       *arrIPtr=(int)arrOut.size();
10913     }
10914   if(arr->getNumberOfTuples()==(int)arrOut.size())
10915     return false;
10916   arr->alloc((int)arrOut.size(),1);
10917   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10918   return true;
10919 }
10920
10921 /*!
10922  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10923  * (\ref numbering-indirect).
10924  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10925  * The selection of extraction is done standardly in new2old format.
10926  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10927  *
10928  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10929  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10930  * \param [in] arrIn arr origin array from which the extraction will be done.
10931  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10932  * \param [out] arrOut the resulting array
10933  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10934  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
10935  */
10936 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10937                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10938 {
10939   if(!arrIn || !arrIndxIn)
10940     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10941   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10942   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10943     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10944   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10945   const int *arrInPtr=arrIn->getConstPointer();
10946   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10947   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10948   if(nbOfGrps<0)
10949     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10950   int maxSizeOfArr=arrIn->getNumberOfTuples();
10951   MCAuto<DataArrayInt> arro=DataArrayInt::New();
10952   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
10953   arrIo->alloc((int)(sz+1),1);
10954   const int *idsIt=idsOfSelectBg;
10955   int *work=arrIo->getPointer();
10956   *work++=0;
10957   int lgth=0;
10958   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10959     {
10960       if(*idsIt>=0 && *idsIt<nbOfGrps)
10961         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10962       else
10963         {
10964           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10965           throw INTERP_KERNEL::Exception(oss.str().c_str());
10966         }
10967       if(lgth>=work[-1])
10968         *work=lgth;
10969       else
10970         {
10971           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10972           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10973           throw INTERP_KERNEL::Exception(oss.str().c_str());
10974         }
10975     }
10976   arro->alloc(lgth,1);
10977   work=arro->getPointer();
10978   idsIt=idsOfSelectBg;
10979   for(std::size_t i=0;i<sz;i++,idsIt++)
10980     {
10981       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10982         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10983       else
10984         {
10985           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10986           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10987           throw INTERP_KERNEL::Exception(oss.str().c_str());
10988         }
10989     }
10990   arrOut=arro.retn();
10991   arrIndexOut=arrIo.retn();
10992 }
10993
10994 /*!
10995  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10996  * (\ref numbering-indirect).
10997  * 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 ).
10998  * The selection of extraction is done standardly in new2old format.
10999  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
11000  *
11001  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
11002  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
11003  * \param [in] idsOfSelectStep
11004  * \param [in] arrIn arr origin array from which the extraction will be done.
11005  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11006  * \param [out] arrOut the resulting array
11007  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11008  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
11009  */
11010 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11011                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11012 {
11013   if(!arrIn || !arrIndxIn)
11014     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
11015   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
11016   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
11017     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
11018   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
11019   const int *arrInPtr=arrIn->getConstPointer();
11020   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11021   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
11022   if(nbOfGrps<0)
11023     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
11024   int maxSizeOfArr=arrIn->getNumberOfTuples();
11025   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11026   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11027   arrIo->alloc((int)(sz+1),1);
11028   int idsIt=idsOfSelectStart;
11029   int *work=arrIo->getPointer();
11030   *work++=0;
11031   int lgth=0;
11032   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
11033     {
11034       if(idsIt>=0 && idsIt<nbOfGrps)
11035         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
11036       else
11037         {
11038           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
11039           throw INTERP_KERNEL::Exception(oss.str().c_str());
11040         }
11041       if(lgth>=work[-1])
11042         *work=lgth;
11043       else
11044         {
11045           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
11046           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
11047           throw INTERP_KERNEL::Exception(oss.str().c_str());
11048         }
11049     }
11050   arro->alloc(lgth,1);
11051   work=arro->getPointer();
11052   idsIt=idsOfSelectStart;
11053   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
11054     {
11055       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
11056         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
11057       else
11058         {
11059           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
11060           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
11061           throw INTERP_KERNEL::Exception(oss.str().c_str());
11062         }
11063     }
11064   arrOut=arro.retn();
11065   arrIndexOut=arrIo.retn();
11066 }
11067
11068 /*!
11069  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11070  * 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
11071  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11072  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11073  *
11074  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11075  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11076  * \param [in] arrIn arr origin array from which the extraction will be done.
11077  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11078  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
11079  * \param [in] srcArrIndex index array of \b srcArr
11080  * \param [out] arrOut the resulting array
11081  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11082  * 
11083  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11084  */
11085 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11086                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11087                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11088 {
11089   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11090     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11091   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11092   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11093   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11094   std::vector<bool> v(nbOfTuples,true);
11095   int offset=0;
11096   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11097   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11098   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11099     {
11100       if(*it>=0 && *it<nbOfTuples)
11101         {
11102           v[*it]=false;
11103           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11104         }
11105       else
11106         {
11107           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11108           throw INTERP_KERNEL::Exception(oss.str().c_str());
11109         }
11110     }
11111   srcArrIndexPtr=srcArrIndex->getConstPointer();
11112   arrIo->alloc(nbOfTuples+1,1);
11113   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11114   const int *arrInPtr=arrIn->getConstPointer();
11115   const int *srcArrPtr=srcArr->getConstPointer();
11116   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11117   int *arroPtr=arro->getPointer();
11118   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11119     {
11120       if(v[ii])
11121         {
11122           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11123           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11124         }
11125       else
11126         {
11127           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11128           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11129           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11130         }
11131     }
11132   arrOut=arro.retn();
11133   arrIndexOut=arrIo.retn();
11134 }
11135
11136 /*!
11137  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11138  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11139  *
11140  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11141  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11142  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11143  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11144  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11145  * \param [in] srcArrIndex index array of \b srcArr
11146  * 
11147  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11148  */
11149 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11150                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11151 {
11152   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11153     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11154   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11155   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11156   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11157   int *arrInOutPtr=arrInOut->getPointer();
11158   const int *srcArrPtr=srcArr->getConstPointer();
11159   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11160     {
11161       if(*it>=0 && *it<nbOfTuples)
11162         {
11163           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11164             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11165           else
11166             {
11167               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] !";
11168               throw INTERP_KERNEL::Exception(oss.str().c_str());
11169             }
11170         }
11171       else
11172         {
11173           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11174           throw INTERP_KERNEL::Exception(oss.str().c_str());
11175         }
11176     }
11177 }
11178
11179 /*!
11180  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11181  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11182  * 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]].
11183  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11184  * A negative value in \b arrIn means that it is ignored.
11185  * 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.
11186  * 
11187  * \param [in] arrIn arr origin array from which the extraction will be done.
11188  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11189  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11190  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11191  */
11192 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11193 {
11194   int seed=0,nbOfDepthPeelingPerformed=0;
11195   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11196 }
11197
11198 /*!
11199  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11200  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11201  * 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]].
11202  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11203  * A negative value in \b arrIn means that it is ignored.
11204  * 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.
11205  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11206  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11207  * \param [in] arrIn arr origin array from which the extraction will be done.
11208  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11209  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11210  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11211  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11212  * \sa MEDCouplingUMesh::partitionBySpreadZone
11213  */
11214 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11215 {
11216   nbOfDepthPeelingPerformed=0;
11217   if(!arrIndxIn)
11218     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11219   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11220   if(nbOfTuples<=0)
11221     {
11222       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11223       return ret;
11224     }
11225   //
11226   std::vector<bool> fetched(nbOfTuples,false);
11227   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11228 }
11229
11230 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11231 {
11232   nbOfDepthPeelingPerformed=0;
11233   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11234     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11235   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11236   std::vector<bool> fetched2(nbOfTuples,false);
11237   int i=0;
11238   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11239     {
11240       if(*seedElt>=0 && *seedElt<nbOfTuples)
11241         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11242       else
11243         { std::ostringstream oss; oss << "MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : At pos #" << i << " of seeds value is " << *seedElt << "! Should be in [0," << nbOfTuples << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
11244     }
11245   const int *arrInPtr=arrIn->getConstPointer();
11246   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11247   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11248   std::vector<int> idsToFetch1(seedBg,seedEnd);
11249   std::vector<int> idsToFetch2;
11250   std::vector<int> *idsToFetch=&idsToFetch1;
11251   std::vector<int> *idsToFetchOther=&idsToFetch2;
11252   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11253     {
11254       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11255         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11256           if(!fetched[*it2])
11257             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11258       std::swap(idsToFetch,idsToFetchOther);
11259       idsToFetchOther->clear();
11260       nbOfDepthPeelingPerformed++;
11261     }
11262   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11263   i=0;
11264   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11265   int *retPtr=ret->getPointer();
11266   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11267     if(*it)
11268       *retPtr++=i;
11269   return ret.retn();
11270 }
11271
11272 /*!
11273  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11274  * 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
11275  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11276  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11277  *
11278  * \param [in] start begin of set of ids of the input extraction (included)
11279  * \param [in] end end of set of ids of the input extraction (excluded)
11280  * \param [in] step step of the set of ids in range mode.
11281  * \param [in] arrIn arr origin array from which the extraction will be done.
11282  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11283  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11284  * \param [in] srcArrIndex index array of \b srcArr
11285  * \param [out] arrOut the resulting array
11286  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11287  * 
11288  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11289  */
11290 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11291                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11292                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11293 {
11294   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11295     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
11296   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11297   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11298   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11299   int offset=0;
11300   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11301   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11302   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
11303   int it=start;
11304   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11305     {
11306       if(it>=0 && it<nbOfTuples)
11307         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11308       else
11309         {
11310           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11311           throw INTERP_KERNEL::Exception(oss.str().c_str());
11312         }
11313     }
11314   srcArrIndexPtr=srcArrIndex->getConstPointer();
11315   arrIo->alloc(nbOfTuples+1,1);
11316   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11317   const int *arrInPtr=arrIn->getConstPointer();
11318   const int *srcArrPtr=srcArr->getConstPointer();
11319   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11320   int *arroPtr=arro->getPointer();
11321   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11322     {
11323       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11324       if(pos<0)
11325         {
11326           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11327           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11328         }
11329       else
11330         {
11331           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11332           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11333         }
11334     }
11335   arrOut=arro.retn();
11336   arrIndexOut=arrIo.retn();
11337 }
11338
11339 /*!
11340  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11341  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11342  *
11343  * \param [in] start begin of set of ids of the input extraction (included)
11344  * \param [in] end end of set of ids of the input extraction (excluded)
11345  * \param [in] step step of the set of ids in range mode.
11346  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11347  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11348  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11349  * \param [in] srcArrIndex index array of \b srcArr
11350  * 
11351  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11352  */
11353 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11354                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11355 {
11356   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11357     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
11358   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11359   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11360   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11361   int *arrInOutPtr=arrInOut->getPointer();
11362   const int *srcArrPtr=srcArr->getConstPointer();
11363   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
11364   int it=start;
11365   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11366     {
11367       if(it>=0 && it<nbOfTuples)
11368         {
11369           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11370             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11371           else
11372             {
11373               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11374               throw INTERP_KERNEL::Exception(oss.str().c_str());
11375             }
11376         }
11377       else
11378         {
11379           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11380           throw INTERP_KERNEL::Exception(oss.str().c_str());
11381         }
11382     }
11383 }
11384
11385 /*!
11386  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11387  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11388  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11389  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11390  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11391  * 
11392  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11393  */
11394 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11395 {
11396   checkFullyDefined();
11397   int mdim=getMeshDimension();
11398   int spaceDim=getSpaceDimension();
11399   if(mdim!=spaceDim)
11400     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11401   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11402   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11403   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
11404   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11405   ret->setCoords(getCoords());
11406   ret->allocateCells((int)partition.size());
11407   //
11408   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11409     {
11410       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11411       MCAuto<DataArrayInt> cell;
11412       switch(mdim)
11413       {
11414         case 2:
11415           cell=tmp->buildUnionOf2DMesh();
11416           break;
11417         case 3:
11418           cell=tmp->buildUnionOf3DMesh();
11419           break;
11420         default:
11421           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11422       }
11423
11424       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11425     }
11426   //
11427   ret->finishInsertingCells();
11428   return ret.retn();
11429 }
11430
11431 /*!
11432  * This method partitions \b this into contiguous zone.
11433  * This method only needs a well defined connectivity. Coordinates are not considered here.
11434  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11435  */
11436 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11437 {
11438   int nbOfCellsCur=getNumberOfCells();
11439   std::vector<DataArrayInt *> ret;
11440   if(nbOfCellsCur<=0)
11441     return ret;
11442   DataArrayInt *neigh=0,*neighI=0;
11443   computeNeighborsOfCells(neigh,neighI);
11444   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11445   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11446   std::vector< MCAuto<DataArrayInt> > ret2;
11447   int seed=0;
11448   while(seed<nbOfCellsCur)
11449     {
11450       int nbOfPeelPerformed=0;
11451       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11452       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11453     }
11454   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11455     ret.push_back((*it).retn());
11456   return ret;
11457 }
11458
11459 /*!
11460  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11461  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11462  *
11463  * \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.
11464  * \return a newly allocated DataArrayInt to be managed by the caller.
11465  * \throw In case of \a code has not the right format (typically of size 3*n)
11466  */
11467 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11468 {
11469   MCAuto<DataArrayInt> ret=DataArrayInt::New();
11470   std::size_t nb=code.size()/3;
11471   if(code.size()%3!=0)
11472     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11473   ret->alloc((int)nb,2);
11474   int *retPtr=ret->getPointer();
11475   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11476     {
11477       retPtr[0]=code[3*i+2];
11478       retPtr[1]=code[3*i+2]+code[3*i+1];
11479     }
11480   return ret.retn();
11481 }
11482
11483 /*!
11484  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11485  * All cells in \a this are expected to be linear 3D cells.
11486  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11487  * It leads to an increase to number of cells.
11488  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11489  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11490  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11491  *
11492  * \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.
11493  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11494  * \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. 
11495  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11496  *          an id of old cell producing it. The caller is to delete this array using
11497  *         decrRef() as it is no more needed.
11498  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11499  *
11500  * \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
11501  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11502  * 
11503  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11504  * \throw If \a this is not fully constituted with linear 3D cells.
11505  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11506  */
11507 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11508 {
11509   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11510   checkConnectivityFullyDefined();
11511   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11512     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11513   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11514   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11515   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11516   int *retPt(ret->getPointer());
11517   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11518   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11519   const int *oldc(_nodal_connec->begin());
11520   const int *oldci(_nodal_connec_index->begin());
11521   const double *coords(_coords->begin());
11522   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11523     {
11524       std::vector<int> a; std::vector<double> b;
11525       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11526       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11527       const int *aa(&a[0]);
11528       if(!b.empty())
11529         {
11530           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11531             if(*it<0)
11532               *it=(-(*(it))-1+nbNodes);
11533           addPts->insertAtTheEnd(b.begin(),b.end());
11534           nbNodes+=(int)b.size()/3;
11535         }
11536       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11537         newConn->insertAtTheEnd(aa,aa+4);
11538     }
11539   if(!addPts->empty())
11540     {
11541       addPts->rearrange(3);
11542       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11543       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11544       ret0->setCoords(addPts);
11545     }
11546   else
11547     {
11548       nbOfAdditionalPoints=0;
11549       ret0->setCoords(getCoords());
11550     }
11551   ret0->setNodalConnectivity(newConn);
11552   //
11553   ret->computeOffsetsFull();
11554   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11555   return ret0.retn();
11556 }
11557
11558 /*!
11559  * 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). 
11560  *
11561  * \sa MEDCouplingUMesh::split2DCells
11562  */
11563 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11564 {
11565   checkConnectivityFullyDefined();
11566   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+subNodesInSeg->getNumberOfTuples());
11567   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11568   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11569   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11570   int prevPosOfCi(ciPtr[0]);
11571   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11572     {
11573       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11574       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11575       for(int j=0;j<sz;j++)
11576         {
11577           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11578           for(int k=0;k<sz2;k++)
11579             *cPtr++=subPtr[offset2+k];
11580           if(j!=sz-1)
11581             *cPtr++=oldConn[prevPosOfCi+j+2];
11582           deltaSz+=sz2;
11583         }
11584       prevPosOfCi=ciPtr[1];
11585       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11586     }
11587   if(c->end()!=cPtr)
11588     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11589   _nodal_connec->decrRef();
11590   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11591 }
11592
11593 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11594 {
11595   if(id!=-1)
11596     return id;
11597   else
11598     {
11599       int ret(nodesCnter++);
11600       double newPt[2];
11601       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11602       addCoo.insertAtTheEnd(newPt,newPt+2);
11603       return ret;
11604     }
11605 }
11606
11607 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11608 {
11609   if(id!=-1)
11610     return id;
11611   else
11612     {
11613       int ret(nodesCnter++);
11614       double newPt[2];
11615       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11616       addCoo.insertAtTheEnd(newPt,newPt+2);
11617       return ret;
11618     }
11619 }
11620
11621
11622 /// @cond INTERNAL
11623
11624 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)
11625 {
11626   int tmp[3];
11627   int trueStart(start>=0?start:nbOfEdges+start);
11628   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11629   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11630   if(linOrArc)
11631     {
11632       if(stp-start>1)
11633         {
11634           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11635           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11636           middles.push_back(tmp3+offset);
11637         }
11638       else
11639         middles.push_back(connBg[trueStart+nbOfEdges]);
11640     }
11641 }
11642
11643 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)
11644 {
11645   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11646   newConnOfCell->pushBackSilent(tmpEnd);
11647   if(linOrArc)
11648     {
11649       if(stp-start>1)
11650         {
11651           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11652           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11653           middles.push_back(tmp3+offset);
11654         }
11655       else
11656         middles.push_back(connBg[start+nbOfEdges]);
11657     }
11658 }
11659
11660 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)
11661 {
11662   // only the quadratic point to deal with:
11663   if(linOrArc)
11664     {
11665       if(stp-start>1)
11666         {
11667           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11668           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11669           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11670           middles.push_back(tmp3+offset);
11671         }
11672       else
11673         middles.push_back(connBg[start+nbOfEdges]);
11674     }
11675 }
11676
11677 /// @endcond
11678
11679 /*!
11680  * 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 ) .
11681  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11682  */
11683 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11684 {
11685   std::size_t sz(std::distance(connBg,connEnd));
11686   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11687     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11688   sz--;
11689   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11690   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11691   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11692   unsigned nbOfHit(0); // number of fusions operated
11693   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11694   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
11695   INTERP_KERNEL::NormalizedCellType typeOfSon;
11696   std::vector<int> middles;
11697   bool ret(false);
11698   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11699     {
11700       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11701       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
11702       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11703       posEndElt = posBaseElt+1;
11704
11705       // Look backward first: are the final edges of the cells colinear with the first ones?
11706       // This initializes posBaseElt.
11707       if(nbOfTurn==0)
11708         {
11709           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11710             {
11711               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11712               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11713               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11714               bool isColinear=eint->areColinears();
11715               if(isColinear)
11716                 {
11717                   nbOfHit++;
11718                   posBaseElt--;
11719                   ret=true;
11720                 }
11721               delete eint;
11722               eCand->decrRef();
11723               if(!isColinear)
11724                 break;
11725             }
11726         }
11727       // Now move forward:
11728       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11729       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11730         {
11731           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11732           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11733           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11734           bool isColinear(eint->areColinears());
11735           if(isColinear)
11736             {
11737               nbOfHit++;
11738               posEndElt++;
11739               ret=true;
11740             }
11741           delete eint;
11742           eCand->decrRef();
11743           if(!isColinear)
11744               break;
11745         }
11746       //push [posBaseElt,posEndElt) in newConnOfCell using e
11747       // 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!
11748       if(nbOfTurn==0)
11749         // at the begining of the connectivity (insert type)
11750         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11751       else if((nbOfHit+nbOfTurn) != (nbs-1))
11752         // in the middle
11753         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11754       if ((nbOfHit+nbOfTurn) == (nbs-1))
11755         // at the end (only quad points to deal with)
11756         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11757       posBaseElt=posEndElt;
11758       e->decrRef();
11759     }
11760   if(!middles.empty())
11761     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11762   return ret;
11763 }
11764
11765 /*!
11766  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11767  *
11768  * \return  int - the number of new nodes created.
11769  * \sa MEDCouplingUMesh::split2DCells
11770  */
11771 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11772 {
11773   checkConsistencyLight();
11774   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11775   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11776   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11777   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11778   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11779   const double *oldCoordsPtr(getCoords()->begin());
11780   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11781   int prevPosOfCi(ciPtr[0]);
11782   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11783     {
11784       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11785       for(int j=0;j<sz;j++)
11786         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11787       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11788       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11789         {
11790           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11791           if(sz2==0)
11792             {
11793               if(j<sz-1)
11794                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11795               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11796               continue;
11797             }
11798           std::vector<INTERP_KERNEL::Node *> ns(3);
11799           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11800           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11801           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11802           MCAuto<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11803           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11804             {
11805               cPtr[1]=subPtr[offset2+k];
11806               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11807             }
11808           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11809           if(j!=sz-1)
11810             { cPtr[1]=tmpEnd; }
11811           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11812         }
11813       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11814       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11815     }
11816   if(c->end()!=cPtr)
11817     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11818   _nodal_connec->decrRef();
11819   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11820   addCoo->rearrange(2);
11821   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11822   setCoords(coo);
11823   return addCoo->getNumberOfTuples();
11824 }
11825
11826 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11827 {
11828   if(nodalConnec && nodalConnecIndex)
11829     {
11830       types.clear();
11831       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11832       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11833       if(nbOfElem>0)
11834         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11835           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11836     }
11837 }
11838
11839 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11840     _own_cell(true),_cell_id(-1),_nb_cell(0)
11841 {
11842   if(mesh)
11843     {
11844       mesh->incrRef();
11845       _nb_cell=mesh->getNumberOfCells();
11846     }
11847 }
11848
11849 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11850 {
11851   if(_mesh)
11852     _mesh->decrRef();
11853   if(_own_cell)
11854     delete _cell;
11855 }
11856
11857 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11858     _own_cell(false),_cell_id(bg-1),
11859     _nb_cell(end)
11860 {
11861   if(mesh)
11862     mesh->incrRef();
11863 }
11864
11865 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11866 {
11867   _cell_id++;
11868   if(_cell_id<_nb_cell)
11869     {
11870       _cell->next();
11871       return _cell;
11872     }
11873   else
11874     return 0;
11875 }
11876
11877 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11878 {
11879   if(_mesh)
11880     _mesh->incrRef();
11881 }
11882
11883 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11884 {
11885   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11886 }
11887
11888 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11889 {
11890   if(_mesh)
11891     _mesh->decrRef();
11892 }
11893
11894 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11895     _itc(itc),
11896     _bg(bg),_end(end)
11897 {
11898   if(_mesh)
11899     _mesh->incrRef();
11900 }
11901
11902 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11903 {
11904   if(_mesh)
11905     _mesh->decrRef();
11906 }
11907
11908 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11909 {
11910   return _type;
11911 }
11912
11913 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11914 {
11915   return _end-_bg;
11916 }
11917
11918 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11919 {
11920   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11921 }
11922
11923 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11924 {
11925   if(mesh)
11926     {
11927       mesh->incrRef();
11928       _nb_cell=mesh->getNumberOfCells();
11929     }
11930 }
11931
11932 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11933 {
11934   if(_mesh)
11935     _mesh->decrRef();
11936   delete _cell;
11937 }
11938
11939 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11940 {
11941   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11942   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11943   if(_cell_id<_nb_cell)
11944     {
11945       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11946       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
11947       int startId=_cell_id;
11948       _cell_id+=nbOfElems;
11949       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11950     }
11951   else
11952     return 0;
11953 }
11954
11955 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11956 {
11957   if(mesh)
11958     {
11959       _conn=mesh->getNodalConnectivity()->getPointer();
11960       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11961     }
11962 }
11963
11964 void MEDCouplingUMeshCell::next()
11965 {
11966   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11967     {
11968       _conn+=_conn_lgth;
11969       _conn_indx++;
11970     }
11971   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11972 }
11973
11974 std::string MEDCouplingUMeshCell::repr() const
11975 {
11976   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11977     {
11978       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11979       oss << " : ";
11980       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11981       return oss.str();
11982     }
11983   else
11984     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11985 }
11986
11987 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11988 {
11989   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11990     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11991   else
11992     return INTERP_KERNEL::NORM_ERROR;
11993 }
11994
11995 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11996 {
11997   lgth=_conn_lgth;
11998   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11999     return _conn;
12000   else
12001     return 0;
12002 }